blob: 8d0d6ae81493ad25ff5e2c9f3f58d681392b17fe [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
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00004PyDoc_STRVAR(xxsubtype__doc__,
Tim Peters65760b22001-12-10 22:53:30 +00005"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"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00008"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 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000022 PyListObject list;
23 int state;
Tim Peters6d6c1a32001-08-02 04:15:00 +000024} spamlistobject;
25
26static PyObject *
27spamlist_getstate(spamlistobject *self, PyObject *args)
28{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000029 if (!PyArg_ParseTuple(args, ":getstate"))
30 return NULL;
31 return PyLong_FromLong(self->state);
Tim Peters6d6c1a32001-08-02 04:15:00 +000032}
33
34static PyObject *
35spamlist_setstate(spamlistobject *self, PyObject *args)
36{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000037 int state;
Tim Peters6d6c1a32001-08-02 04:15:00 +000038
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000039 if (!PyArg_ParseTuple(args, "i:setstate", &state))
40 return NULL;
41 self->state = state;
42 Py_INCREF(Py_None);
43 return Py_None;
Tim Peters6d6c1a32001-08-02 04:15:00 +000044}
45
Fred Drakef841aa62002-03-28 15:49:54 +000046static PyObject *
47spamlist_specialmeth(PyObject *self, PyObject *args, PyObject *kw)
48{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000049 PyObject *result = PyTuple_New(3);
Fred Drakef841aa62002-03-28 15:49:54 +000050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000051 if (result != NULL) {
52 if (self == NULL)
53 self = Py_None;
54 if (kw == NULL)
55 kw = Py_None;
56 Py_INCREF(self);
57 PyTuple_SET_ITEM(result, 0, self);
58 Py_INCREF(args);
59 PyTuple_SET_ITEM(result, 1, args);
60 Py_INCREF(kw);
61 PyTuple_SET_ITEM(result, 2, kw);
62 }
63 return result;
Fred Drakef841aa62002-03-28 15:49:54 +000064}
65
Tim Peters6d6c1a32001-08-02 04:15:00 +000066static PyMethodDef spamlist_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000067 {"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},
Tim Peters6d6c1a32001-08-02 04:15:00 +000080};
81
Tim Peters6d6c1a32001-08-02 04:15:00 +000082static int
83spamlist_init(spamlistobject *self, PyObject *args, PyObject *kwds)
84{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000085 if (PyList_Type.tp_init((PyObject *)self, args, kwds) < 0)
86 return -1;
87 self->state = 0;
88 return 0;
Tim Peters6d6c1a32001-08-02 04:15:00 +000089}
90
Guido van Rossum88dcf032001-08-15 18:18:58 +000091static PyObject *
92spamlist_state_get(spamlistobject *self)
93{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000094 return PyLong_FromLong(self->state);
Guido van Rossum88dcf032001-08-15 18:18:58 +000095}
96
Guido van Rossum32d34c82001-09-20 21:45:26 +000097static PyGetSetDef spamlist_getsets[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000098 {"state", (getter)spamlist_state_get, NULL,
99 PyDoc_STR("an int variable for demonstration purposes")},
100 {0}
Guido van Rossum88dcf032001-08-15 18:18:58 +0000101};
102
Tim Peters6d6c1a32001-08-02 04:15:00 +0000103static PyTypeObject spamlist_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000104 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_reserved */
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 */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000142};
143
144/* spamdict -- a dict subtype */
145
146typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000147 PyDictObject dict;
148 int state;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000149} spamdictobject;
150
151static PyObject *
152spamdict_getstate(spamdictobject *self, PyObject *args)
153{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000154 if (!PyArg_ParseTuple(args, ":getstate"))
155 return NULL;
156 return PyLong_FromLong(self->state);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000157}
158
159static PyObject *
160spamdict_setstate(spamdictobject *self, PyObject *args)
161{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000162 int state;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000163
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000164 if (!PyArg_ParseTuple(args, "i:setstate", &state))
165 return NULL;
166 self->state = state;
167 Py_INCREF(Py_None);
168 return Py_None;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000169}
170
171static PyMethodDef spamdict_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000172 {"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},
Tim Peters6d6c1a32001-08-02 04:15:00 +0000177};
178
Tim Peters6d6c1a32001-08-02 04:15:00 +0000179static int
180spamdict_init(spamdictobject *self, PyObject *args, PyObject *kwds)
181{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000182 if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
183 return -1;
184 self->state = 0;
185 return 0;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000186}
187
Guido van Rossum6f799372001-09-20 20:46:19 +0000188static PyMemberDef spamdict_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000189 {"state", T_INT, offsetof(spamdictobject, state), READONLY,
190 PyDoc_STR("an int variable for demonstration purposes")},
191 {0}
Guido van Rossume6b90ea2001-08-15 18:09:11 +0000192};
193
Tim Peters6d6c1a32001-08-02 04:15:00 +0000194static PyTypeObject spamdict_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 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_reserved */
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 */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000233};
234
Neil Schemenauer26775122001-10-21 22:26:43 +0000235static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +0000236spam_bench(PyObject *self, PyObject *args)
237{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000238 PyObject *obj, *name, *res;
239 int n = 1000;
240 time_t t0, t1;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000241
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242 if (!PyArg_ParseTuple(args, "OS|i", &obj, &name, &n))
243 return NULL;
244 t0 = clock();
245 while (--n >= 0) {
246 res = PyObject_GetAttr(obj, name);
247 if (res == NULL)
248 return NULL;
249 Py_DECREF(res);
250 }
251 t1 = clock();
252 return PyFloat_FromDouble((double)(t1-t0) / CLOCKS_PER_SEC);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000253}
254
255static PyMethodDef xxsubtype_functions[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000256 {"bench", spam_bench, METH_VARARGS},
257 {NULL, NULL} /* sentinel */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000258};
259
Nick Coghland5cacbb2015-05-23 22:24:10 +1000260static int
261xxsubtype_exec(PyObject* m)
262{
263 /* Fill in deferred data addresses. This must be done before
264 PyType_Ready() is called. Note that PyType_Ready() automatically
265 initializes the ob.ob_type field to &PyType_Type if it's NULL,
266 so it's not necessary to fill in ob_type first. */
267 spamdict_type.tp_base = &PyDict_Type;
268 if (PyType_Ready(&spamdict_type) < 0)
269 return -1;
270
271 spamlist_type.tp_base = &PyList_Type;
272 if (PyType_Ready(&spamlist_type) < 0)
273 return -1;
274
275 if (PyType_Ready(&spamlist_type) < 0)
276 return -1;
277 if (PyType_Ready(&spamdict_type) < 0)
278 return -1;
279
280 Py_INCREF(&spamlist_type);
281 if (PyModule_AddObject(m, "spamlist",
282 (PyObject *) &spamlist_type) < 0)
283 return -1;
284
285 Py_INCREF(&spamdict_type);
286 if (PyModule_AddObject(m, "spamdict",
287 (PyObject *) &spamdict_type) < 0)
288 return -1;
289 return 0;
290}
291
292static struct PyModuleDef_Slot xxsubtype_slots[] = {
293 {Py_mod_exec, xxsubtype_exec},
294 {0, NULL},
295};
296
Martin v. Löwis1a214512008-06-11 05:26:20 +0000297static struct PyModuleDef xxsubtypemodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000298 PyModuleDef_HEAD_INIT,
299 "xxsubtype",
300 xxsubtype__doc__,
Nick Coghland5cacbb2015-05-23 22:24:10 +1000301 0,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000302 xxsubtype_functions,
Nick Coghland5cacbb2015-05-23 22:24:10 +1000303 xxsubtype_slots,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000304 NULL,
305 NULL,
306 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000307};
308
309
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000310PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000311PyInit_xxsubtype(void)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000312{
Nick Coghland5cacbb2015-05-23 22:24:10 +1000313 return PyModuleDef_Init(&xxsubtypemodule);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000314}