Line data Source code
1 : #include "Python.h"
2 : #include "structmember.h"
3 :
4 : PyDoc_STRVAR(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.");
9 :
10 : /* 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 :
19 : /* spamlist -- a list subtype */
20 :
21 : typedef struct {
22 : PyListObject list;
23 : int state;
24 : } spamlistobject;
25 :
26 : static PyObject *
27 0 : spamlist_getstate(spamlistobject *self, PyObject *args)
28 : {
29 0 : if (!PyArg_ParseTuple(args, ":getstate"))
30 0 : return NULL;
31 0 : return PyInt_FromLong(self->state);
32 : }
33 :
34 : static PyObject *
35 0 : spamlist_setstate(spamlistobject *self, PyObject *args)
36 : {
37 : int state;
38 :
39 0 : if (!PyArg_ParseTuple(args, "i:setstate", &state))
40 0 : return NULL;
41 0 : self->state = state;
42 0 : Py_INCREF(Py_None);
43 0 : return Py_None;
44 : }
45 :
46 : static PyObject *
47 0 : spamlist_specialmeth(PyObject *self, PyObject *args, PyObject *kw)
48 : {
49 0 : PyObject *result = PyTuple_New(3);
50 :
51 0 : if (result != NULL) {
52 0 : if (self == NULL)
53 0 : self = Py_None;
54 0 : if (kw == NULL)
55 0 : kw = Py_None;
56 0 : Py_INCREF(self);
57 0 : PyTuple_SET_ITEM(result, 0, self);
58 0 : Py_INCREF(args);
59 0 : PyTuple_SET_ITEM(result, 1, args);
60 0 : Py_INCREF(kw);
61 0 : PyTuple_SET_ITEM(result, 2, kw);
62 : }
63 0 : return result;
64 : }
65 :
66 : static PyMethodDef spamlist_methods[] = {
67 : {"getstate", (PyCFunction)spamlist_getstate, METH_VARARGS,
68 : PyDoc_STR("getstate() -> state")},
69 : {"setstate", (PyCFunction)spamlist_setstate, METH_VARARGS,
70 : PyDoc_STR("setstate(state)")},
71 : /* These entries differ only in the flags; they are used by the tests
72 : in test.test_descr. */
73 : {"classmeth", (PyCFunction)spamlist_specialmeth,
74 : METH_VARARGS | METH_KEYWORDS | METH_CLASS,
75 : PyDoc_STR("classmeth(*args, **kw)")},
76 : {"staticmeth", (PyCFunction)spamlist_specialmeth,
77 : METH_VARARGS | METH_KEYWORDS | METH_STATIC,
78 : PyDoc_STR("staticmeth(*args, **kw)")},
79 : {NULL, NULL},
80 : };
81 :
82 : static int
83 0 : spamlist_init(spamlistobject *self, PyObject *args, PyObject *kwds)
84 : {
85 0 : if (PyList_Type.tp_init((PyObject *)self, args, kwds) < 0)
86 0 : return -1;
87 0 : self->state = 0;
88 0 : return 0;
89 : }
90 :
91 : static PyObject *
92 0 : spamlist_state_get(spamlistobject *self)
93 : {
94 0 : return PyInt_FromLong(self->state);
95 : }
96 :
97 : static PyGetSetDef spamlist_getsets[] = {
98 : {"state", (getter)spamlist_state_get, NULL,
99 : PyDoc_STR("an int variable for demonstration purposes")},
100 : {0}
101 : };
102 :
103 : static PyTypeObject spamlist_type = {
104 : PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
105 : "xxsubtype.spamlist",
106 : sizeof(spamlistobject),
107 : 0,
108 : 0, /* tp_dealloc */
109 : 0, /* tp_print */
110 : 0, /* tp_getattr */
111 : 0, /* tp_setattr */
112 : 0, /* tp_compare */
113 : 0, /* tp_repr */
114 : 0, /* tp_as_number */
115 : 0, /* tp_as_sequence */
116 : 0, /* tp_as_mapping */
117 : 0, /* tp_hash */
118 : 0, /* tp_call */
119 : 0, /* tp_str */
120 : 0, /* tp_getattro */
121 : 0, /* tp_setattro */
122 : 0, /* tp_as_buffer */
123 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
124 : 0, /* tp_doc */
125 : 0, /* tp_traverse */
126 : 0, /* tp_clear */
127 : 0, /* tp_richcompare */
128 : 0, /* tp_weaklistoffset */
129 : 0, /* tp_iter */
130 : 0, /* tp_iternext */
131 : spamlist_methods, /* tp_methods */
132 : 0, /* tp_members */
133 : spamlist_getsets, /* tp_getset */
134 : DEFERRED_ADDRESS(&PyList_Type), /* tp_base */
135 : 0, /* tp_dict */
136 : 0, /* tp_descr_get */
137 : 0, /* tp_descr_set */
138 : 0, /* tp_dictoffset */
139 : (initproc)spamlist_init, /* tp_init */
140 : 0, /* tp_alloc */
141 : 0, /* tp_new */
142 : };
143 :
144 : /* spamdict -- a dict subtype */
145 :
146 : typedef struct {
147 : PyDictObject dict;
148 : int state;
149 : } spamdictobject;
150 :
151 : static PyObject *
152 0 : spamdict_getstate(spamdictobject *self, PyObject *args)
153 : {
154 0 : if (!PyArg_ParseTuple(args, ":getstate"))
155 0 : return NULL;
156 0 : return PyInt_FromLong(self->state);
157 : }
158 :
159 : static PyObject *
160 0 : spamdict_setstate(spamdictobject *self, PyObject *args)
161 : {
162 : int state;
163 :
164 0 : if (!PyArg_ParseTuple(args, "i:setstate", &state))
165 0 : return NULL;
166 0 : self->state = state;
167 0 : Py_INCREF(Py_None);
168 0 : return Py_None;
169 : }
170 :
171 : static PyMethodDef spamdict_methods[] = {
172 : {"getstate", (PyCFunction)spamdict_getstate, METH_VARARGS,
173 : PyDoc_STR("getstate() -> state")},
174 : {"setstate", (PyCFunction)spamdict_setstate, METH_VARARGS,
175 : PyDoc_STR("setstate(state)")},
176 : {NULL, NULL},
177 : };
178 :
179 : static int
180 0 : spamdict_init(spamdictobject *self, PyObject *args, PyObject *kwds)
181 : {
182 0 : if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
183 0 : return -1;
184 0 : self->state = 0;
185 0 : return 0;
186 : }
187 :
188 : static PyMemberDef spamdict_members[] = {
189 : {"state", T_INT, offsetof(spamdictobject, state), READONLY,
190 : PyDoc_STR("an int variable for demonstration purposes")},
191 : {0}
192 : };
193 :
194 : static PyTypeObject spamdict_type = {
195 : PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
196 : "xxsubtype.spamdict",
197 : sizeof(spamdictobject),
198 : 0,
199 : 0, /* tp_dealloc */
200 : 0, /* tp_print */
201 : 0, /* tp_getattr */
202 : 0, /* tp_setattr */
203 : 0, /* tp_compare */
204 : 0, /* tp_repr */
205 : 0, /* tp_as_number */
206 : 0, /* tp_as_sequence */
207 : 0, /* tp_as_mapping */
208 : 0, /* tp_hash */
209 : 0, /* tp_call */
210 : 0, /* tp_str */
211 : 0, /* tp_getattro */
212 : 0, /* tp_setattro */
213 : 0, /* tp_as_buffer */
214 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
215 : 0, /* tp_doc */
216 : 0, /* tp_traverse */
217 : 0, /* tp_clear */
218 : 0, /* tp_richcompare */
219 : 0, /* tp_weaklistoffset */
220 : 0, /* tp_iter */
221 : 0, /* tp_iternext */
222 : spamdict_methods, /* tp_methods */
223 : spamdict_members, /* tp_members */
224 : 0, /* tp_getset */
225 : DEFERRED_ADDRESS(&PyDict_Type), /* tp_base */
226 : 0, /* tp_dict */
227 : 0, /* tp_descr_get */
228 : 0, /* tp_descr_set */
229 : 0, /* tp_dictoffset */
230 : (initproc)spamdict_init, /* tp_init */
231 : 0, /* tp_alloc */
232 : 0, /* tp_new */
233 : };
234 :
235 : static PyObject *
236 0 : spam_bench(PyObject *self, PyObject *args)
237 : {
238 : PyObject *obj, *name, *res;
239 0 : int n = 1000;
240 : time_t t0, t1;
241 :
242 0 : if (!PyArg_ParseTuple(args, "OS|i", &obj, &name, &n))
243 0 : return NULL;
244 0 : t0 = clock();
245 0 : while (--n >= 0) {
246 0 : res = PyObject_GetAttr(obj, name);
247 0 : if (res == NULL)
248 0 : return NULL;
249 0 : Py_DECREF(res);
250 : }
251 0 : t1 = clock();
252 0 : return PyFloat_FromDouble((double)(t1-t0) / CLOCKS_PER_SEC);
253 : }
254 :
255 : static PyMethodDef xxsubtype_functions[] = {
256 : {"bench", spam_bench, METH_VARARGS},
257 : {NULL, NULL} /* sentinel */
258 : };
259 :
260 : PyMODINIT_FUNC
261 0 : initxxsubtype(void)
262 : {
263 : PyObject *m;
264 :
265 : /* Fill in deferred data addresses. This must be done before
266 : PyType_Ready() is called. Note that PyType_Ready() automatically
267 : initializes the ob.ob_type field to &PyType_Type if it's NULL,
268 : so it's not necessary to fill in ob_type first. */
269 0 : spamdict_type.tp_base = &PyDict_Type;
270 0 : if (PyType_Ready(&spamdict_type) < 0)
271 0 : return;
272 :
273 0 : spamlist_type.tp_base = &PyList_Type;
274 0 : if (PyType_Ready(&spamlist_type) < 0)
275 0 : return;
276 :
277 0 : m = Py_InitModule3("xxsubtype",
278 : xxsubtype_functions,
279 : xxsubtype__doc__);
280 0 : if (m == NULL)
281 0 : return;
282 :
283 0 : if (PyType_Ready(&spamlist_type) < 0)
284 0 : return;
285 0 : if (PyType_Ready(&spamdict_type) < 0)
286 0 : return;
287 :
288 0 : Py_INCREF(&spamlist_type);
289 0 : if (PyModule_AddObject(m, "spamlist",
290 : (PyObject *) &spamlist_type) < 0)
291 0 : return;
292 :
293 0 : Py_INCREF(&spamdict_type);
294 0 : if (PyModule_AddObject(m, "spamdict",
295 : (PyObject *) &spamdict_type) < 0)
296 0 : return;
297 : }
|