blob: f3d8e89ed74e10cf4bc965a786fe75b7826e8c62 [file] [log] [blame]
Tim Peters6d6c1a32001-08-02 04:15:00 +00001#include "Python.h"
Guido van Rossume6b90ea2001-08-15 18:09:11 +00002#include "structmember.h"
Tim Peters6d6c1a32001-08-02 04:15:00 +00003
Tim Peters65760b22001-12-10 22:53:30 +00004static char xxsubtype__doc__[] =
5"xxsubtype is an example module showing how to subtype builtin types from C.\n"
6"test_descr.py in the standard test suite requires it in order to complete.\n"
7"If you don't care about the examples, and don't intend to run the Python\n"
8"test suite, you can recompile Python without Modules/xxsubtype.c.";
Tim Peters6d6c1a32001-08-02 04:15:00 +00009
Tim Petersdd5c05f2001-12-17 01:27:01 +000010/* We link this module statically for convenience. If compiled as a shared
11 library instead, some compilers don't allow addresses of Python objects
12 defined in other libraries to be used in static initializers here. The
13 DEFERRED_ADDRESS macro is used to tag the slots where such addresses
14 appear; the module init function must fill in the tagged slots at runtime.
15 The argument is for documentation -- the macro ignores it.
16*/
17#define DEFERRED_ADDRESS(ADDR) 0
18
Tim Peters6d6c1a32001-08-02 04:15:00 +000019/* spamlist -- a list subtype */
20
21typedef struct {
22 PyListObject list;
23 int state;
24} spamlistobject;
25
26static PyObject *
27spamlist_getstate(spamlistobject *self, PyObject *args)
28{
29 if (!PyArg_ParseTuple(args, ":getstate"))
30 return NULL;
31 return PyInt_FromLong(self->state);
32}
33
34static PyObject *
35spamlist_setstate(spamlistobject *self, PyObject *args)
36{
37 int state;
38
39 if (!PyArg_ParseTuple(args, "i:setstate", &state))
40 return NULL;
41 self->state = state;
42 Py_INCREF(Py_None);
43 return Py_None;
44}
45
46static PyMethodDef spamlist_methods[] = {
47 {"getstate", (PyCFunction)spamlist_getstate, METH_VARARGS,
48 "getstate() -> state"},
49 {"setstate", (PyCFunction)spamlist_setstate, METH_VARARGS,
50 "setstate(state)"},
51 {NULL, NULL},
52};
53
54staticforward PyTypeObject spamlist_type;
55
56static int
57spamlist_init(spamlistobject *self, PyObject *args, PyObject *kwds)
58{
59 if (PyList_Type.tp_init((PyObject *)self, args, kwds) < 0)
60 return -1;
61 self->state = 0;
62 return 0;
63}
64
Guido van Rossum88dcf032001-08-15 18:18:58 +000065static PyObject *
66spamlist_state_get(spamlistobject *self)
67{
68 return PyInt_FromLong(self->state);
69}
70
Guido van Rossum32d34c82001-09-20 21:45:26 +000071static PyGetSetDef spamlist_getsets[] = {
72 {"state", (getter)spamlist_state_get, NULL,
73 "an int variable for demonstration purposes"},
Guido van Rossum88dcf032001-08-15 18:18:58 +000074 {0}
75};
76
Tim Peters6d6c1a32001-08-02 04:15:00 +000077static PyTypeObject spamlist_type = {
Tim Petersdd5c05f2001-12-17 01:27:01 +000078 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
Tim Peters6d6c1a32001-08-02 04:15:00 +000079 0,
Guido van Rossum83f56cb2001-08-16 09:10:42 +000080 "xxsubtype.spamlist",
Tim Peters6d6c1a32001-08-02 04:15:00 +000081 sizeof(spamlistobject),
82 0,
83 0, /* tp_dealloc */
84 0, /* tp_print */
85 0, /* tp_getattr */
86 0, /* tp_setattr */
87 0, /* tp_compare */
88 0, /* tp_repr */
89 0, /* tp_as_number */
90 0, /* tp_as_sequence */
91 0, /* tp_as_mapping */
92 0, /* tp_hash */
93 0, /* tp_call */
94 0, /* tp_str */
95 0, /* tp_getattro */
96 0, /* tp_setattro */
97 0, /* tp_as_buffer */
98 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
99 0, /* tp_doc */
100 0, /* tp_traverse */
101 0, /* tp_clear */
102 0, /* tp_richcompare */
103 0, /* tp_weaklistoffset */
104 0, /* tp_iter */
105 0, /* tp_iternext */
106 spamlist_methods, /* tp_methods */
107 0, /* tp_members */
Guido van Rossum88dcf032001-08-15 18:18:58 +0000108 spamlist_getsets, /* tp_getset */
Tim Petersdd5c05f2001-12-17 01:27:01 +0000109 DEFERRED_ADDRESS(&PyList_Type), /* tp_base */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000110 0, /* tp_dict */
111 0, /* tp_descr_get */
112 0, /* tp_descr_set */
113 0, /* tp_dictoffset */
114 (initproc)spamlist_init, /* tp_init */
115 0, /* tp_alloc */
116 0, /* tp_new */
117};
118
119/* spamdict -- a dict subtype */
120
121typedef struct {
122 PyDictObject dict;
123 int state;
124} spamdictobject;
125
126static PyObject *
127spamdict_getstate(spamdictobject *self, PyObject *args)
128{
129 if (!PyArg_ParseTuple(args, ":getstate"))
130 return NULL;
131 return PyInt_FromLong(self->state);
132}
133
134static PyObject *
135spamdict_setstate(spamdictobject *self, PyObject *args)
136{
137 int state;
138
139 if (!PyArg_ParseTuple(args, "i:setstate", &state))
140 return NULL;
141 self->state = state;
142 Py_INCREF(Py_None);
143 return Py_None;
144}
145
146static PyMethodDef spamdict_methods[] = {
147 {"getstate", (PyCFunction)spamdict_getstate, METH_VARARGS,
148 "getstate() -> state"},
149 {"setstate", (PyCFunction)spamdict_setstate, METH_VARARGS,
150 "setstate(state)"},
151 {NULL, NULL},
152};
153
154staticforward PyTypeObject spamdict_type;
155
156static int
157spamdict_init(spamdictobject *self, PyObject *args, PyObject *kwds)
158{
159 if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
160 return -1;
161 self->state = 0;
162 return 0;
163}
164
Guido van Rossum6f799372001-09-20 20:46:19 +0000165static PyMemberDef spamdict_members[] = {
166 {"state", T_INT, offsetof(spamdictobject, state), READONLY,
167 "an int variable for demonstration purposes"},
Guido van Rossume6b90ea2001-08-15 18:09:11 +0000168 {0}
169};
170
Tim Peters6d6c1a32001-08-02 04:15:00 +0000171static PyTypeObject spamdict_type = {
Tim Petersdd5c05f2001-12-17 01:27:01 +0000172 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
Tim Peters6d6c1a32001-08-02 04:15:00 +0000173 0,
Guido van Rossum83f56cb2001-08-16 09:10:42 +0000174 "xxsubtype.spamdict",
Tim Peters6d6c1a32001-08-02 04:15:00 +0000175 sizeof(spamdictobject),
176 0,
177 0, /* tp_dealloc */
178 0, /* tp_print */
179 0, /* tp_getattr */
180 0, /* tp_setattr */
181 0, /* tp_compare */
182 0, /* tp_repr */
183 0, /* tp_as_number */
184 0, /* tp_as_sequence */
185 0, /* tp_as_mapping */
186 0, /* tp_hash */
187 0, /* tp_call */
188 0, /* tp_str */
189 0, /* tp_getattro */
190 0, /* tp_setattro */
191 0, /* tp_as_buffer */
192 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
193 0, /* tp_doc */
194 0, /* tp_traverse */
195 0, /* tp_clear */
196 0, /* tp_richcompare */
197 0, /* tp_weaklistoffset */
198 0, /* tp_iter */
199 0, /* tp_iternext */
200 spamdict_methods, /* tp_methods */
Guido van Rossume6b90ea2001-08-15 18:09:11 +0000201 spamdict_members, /* tp_members */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000202 0, /* tp_getset */
Tim Petersdd5c05f2001-12-17 01:27:01 +0000203 DEFERRED_ADDRESS(&PyDict_Type), /* tp_base */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000204 0, /* tp_dict */
205 0, /* tp_descr_get */
206 0, /* tp_descr_set */
207 0, /* tp_dictoffset */
208 (initproc)spamdict_init, /* tp_init */
209 0, /* tp_alloc */
210 0, /* tp_new */
211};
212
Neil Schemenauer26775122001-10-21 22:26:43 +0000213static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +0000214spam_bench(PyObject *self, PyObject *args)
215{
216 PyObject *obj, *name, *res;
217 int n = 1000;
218 time_t t0, t1;
219
220 if (!PyArg_ParseTuple(args, "OS|i", &obj, &name, &n))
221 return NULL;
222 t0 = clock();
223 while (--n >= 0) {
224 res = PyObject_GetAttr(obj, name);
225 if (res == NULL)
226 return NULL;
227 Py_DECREF(res);
228 }
229 t1 = clock();
230 return PyFloat_FromDouble((double)(t1-t0) / CLOCKS_PER_SEC);
231}
232
233static PyMethodDef xxsubtype_functions[] = {
234 {"bench", spam_bench, METH_VARARGS},
235 {NULL, NULL} /* sentinel */
236};
237
238DL_EXPORT(void)
239initxxsubtype(void)
240{
241 PyObject *m, *d;
242
Tim Peters4befff92001-12-17 18:26:19 +0000243 /* Fill in deferred data addresses. This must be done before
244 PyType_Ready() is called. Note that PyType_Ready() automatically
245 initializes the ob.ob_type field to &PyType_Type if it's NULL,
246 so it's not necessary to fill in ob_type first. */
Tim Petersdd5c05f2001-12-17 01:27:01 +0000247 spamdict_type.tp_base = &PyDict_Type;
Guido van Rossuma7b9b3c2001-12-17 17:25:53 +0000248 if (PyType_Ready(&spamdict_type) < 0)
249 return;
Tim Petersdd5c05f2001-12-17 01:27:01 +0000250
Tim Petersdd5c05f2001-12-17 01:27:01 +0000251 spamlist_type.tp_base = &PyList_Type;
Guido van Rossuma7b9b3c2001-12-17 17:25:53 +0000252 if (PyType_Ready(&spamlist_type) < 0)
253 return;
Tim Petersdd5c05f2001-12-17 01:27:01 +0000254
Tim Peters65760b22001-12-10 22:53:30 +0000255 m = Py_InitModule3("xxsubtype",
256 xxsubtype_functions,
257 xxsubtype__doc__);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000258 if (m == NULL)
259 return;
260
Guido van Rossum528b7eb2001-08-07 17:24:28 +0000261 if (PyType_Ready(&spamlist_type) < 0)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000262 return;
Guido van Rossum528b7eb2001-08-07 17:24:28 +0000263 if (PyType_Ready(&spamdict_type) < 0)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000264 return;
265
266 d = PyModule_GetDict(m);
267 if (d == NULL)
268 return;
269
270 Py_INCREF(&spamlist_type);
271 if (PyDict_SetItemString(d, "spamlist",
272 (PyObject *) &spamlist_type) < 0)
273 return;
274
275 Py_INCREF(&spamdict_type);
276 if (PyDict_SetItemString(d, "spamdict",
277 (PyObject *) &spamdict_type) < 0)
278 return;
279}