blob: c20a1c711403f5a112b09bc81dd68f0aa9afb654 [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
4/* Examples showing how to subtype the builtin list and dict types from C. */
5
6/* spamlist -- a list subtype */
7
8typedef struct {
9 PyListObject list;
10 int state;
11} spamlistobject;
12
13static PyObject *
14spamlist_getstate(spamlistobject *self, PyObject *args)
15{
16 if (!PyArg_ParseTuple(args, ":getstate"))
17 return NULL;
18 return PyInt_FromLong(self->state);
19}
20
21static PyObject *
22spamlist_setstate(spamlistobject *self, PyObject *args)
23{
24 int state;
25
26 if (!PyArg_ParseTuple(args, "i:setstate", &state))
27 return NULL;
28 self->state = state;
29 Py_INCREF(Py_None);
30 return Py_None;
31}
32
33static PyMethodDef spamlist_methods[] = {
34 {"getstate", (PyCFunction)spamlist_getstate, METH_VARARGS,
35 "getstate() -> state"},
36 {"setstate", (PyCFunction)spamlist_setstate, METH_VARARGS,
37 "setstate(state)"},
38 {NULL, NULL},
39};
40
41staticforward PyTypeObject spamlist_type;
42
43static int
44spamlist_init(spamlistobject *self, PyObject *args, PyObject *kwds)
45{
46 if (PyList_Type.tp_init((PyObject *)self, args, kwds) < 0)
47 return -1;
48 self->state = 0;
49 return 0;
50}
51
Guido van Rossum88dcf032001-08-15 18:18:58 +000052static PyObject *
53spamlist_state_get(spamlistobject *self)
54{
55 return PyInt_FromLong(self->state);
56}
57
58static struct getsetlist spamlist_getsets[] = {
59 {"state", (getter)spamlist_state_get, NULL, NULL},
60 {0}
61};
62
Tim Peters6d6c1a32001-08-02 04:15:00 +000063static PyTypeObject spamlist_type = {
64 PyObject_HEAD_INIT(&PyType_Type)
65 0,
Guido van Rossum83f56cb2001-08-16 09:10:42 +000066 "xxsubtype.spamlist",
Tim Peters6d6c1a32001-08-02 04:15:00 +000067 sizeof(spamlistobject),
68 0,
69 0, /* tp_dealloc */
70 0, /* tp_print */
71 0, /* tp_getattr */
72 0, /* tp_setattr */
73 0, /* tp_compare */
74 0, /* tp_repr */
75 0, /* tp_as_number */
76 0, /* tp_as_sequence */
77 0, /* tp_as_mapping */
78 0, /* tp_hash */
79 0, /* tp_call */
80 0, /* tp_str */
81 0, /* tp_getattro */
82 0, /* tp_setattro */
83 0, /* tp_as_buffer */
84 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
85 0, /* tp_doc */
86 0, /* tp_traverse */
87 0, /* tp_clear */
88 0, /* tp_richcompare */
89 0, /* tp_weaklistoffset */
90 0, /* tp_iter */
91 0, /* tp_iternext */
92 spamlist_methods, /* tp_methods */
93 0, /* tp_members */
Guido van Rossum88dcf032001-08-15 18:18:58 +000094 spamlist_getsets, /* tp_getset */
Tim Peters6d6c1a32001-08-02 04:15:00 +000095 &PyList_Type, /* tp_base */
96 0, /* tp_dict */
97 0, /* tp_descr_get */
98 0, /* tp_descr_set */
99 0, /* tp_dictoffset */
100 (initproc)spamlist_init, /* tp_init */
101 0, /* tp_alloc */
102 0, /* tp_new */
103};
104
105/* spamdict -- a dict subtype */
106
107typedef struct {
108 PyDictObject dict;
109 int state;
110} spamdictobject;
111
112static PyObject *
113spamdict_getstate(spamdictobject *self, PyObject *args)
114{
115 if (!PyArg_ParseTuple(args, ":getstate"))
116 return NULL;
117 return PyInt_FromLong(self->state);
118}
119
120static PyObject *
121spamdict_setstate(spamdictobject *self, PyObject *args)
122{
123 int state;
124
125 if (!PyArg_ParseTuple(args, "i:setstate", &state))
126 return NULL;
127 self->state = state;
128 Py_INCREF(Py_None);
129 return Py_None;
130}
131
132static PyMethodDef spamdict_methods[] = {
133 {"getstate", (PyCFunction)spamdict_getstate, METH_VARARGS,
134 "getstate() -> state"},
135 {"setstate", (PyCFunction)spamdict_setstate, METH_VARARGS,
136 "setstate(state)"},
137 {NULL, NULL},
138};
139
140staticforward PyTypeObject spamdict_type;
141
142static int
143spamdict_init(spamdictobject *self, PyObject *args, PyObject *kwds)
144{
145 if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
146 return -1;
147 self->state = 0;
148 return 0;
149}
150
Guido van Rossume6b90ea2001-08-15 18:09:11 +0000151static struct memberlist spamdict_members[] = {
152 {"state", T_INT, offsetof(spamdictobject, state), READONLY},
153 {0}
154};
155
Tim Peters6d6c1a32001-08-02 04:15:00 +0000156static PyTypeObject spamdict_type = {
157 PyObject_HEAD_INIT(&PyType_Type)
158 0,
Guido van Rossum83f56cb2001-08-16 09:10:42 +0000159 "xxsubtype.spamdict",
Tim Peters6d6c1a32001-08-02 04:15:00 +0000160 sizeof(spamdictobject),
161 0,
162 0, /* tp_dealloc */
163 0, /* tp_print */
164 0, /* tp_getattr */
165 0, /* tp_setattr */
166 0, /* tp_compare */
167 0, /* tp_repr */
168 0, /* tp_as_number */
169 0, /* tp_as_sequence */
170 0, /* tp_as_mapping */
171 0, /* tp_hash */
172 0, /* tp_call */
173 0, /* tp_str */
174 0, /* tp_getattro */
175 0, /* tp_setattro */
176 0, /* tp_as_buffer */
177 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
178 0, /* tp_doc */
179 0, /* tp_traverse */
180 0, /* tp_clear */
181 0, /* tp_richcompare */
182 0, /* tp_weaklistoffset */
183 0, /* tp_iter */
184 0, /* tp_iternext */
185 spamdict_methods, /* tp_methods */
Guido van Rossume6b90ea2001-08-15 18:09:11 +0000186 spamdict_members, /* tp_members */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000187 0, /* tp_getset */
188 &PyDict_Type, /* tp_base */
189 0, /* tp_dict */
190 0, /* tp_descr_get */
191 0, /* tp_descr_set */
192 0, /* tp_dictoffset */
193 (initproc)spamdict_init, /* tp_init */
194 0, /* tp_alloc */
195 0, /* tp_new */
196};
197
198PyObject *
199spam_bench(PyObject *self, PyObject *args)
200{
201 PyObject *obj, *name, *res;
202 int n = 1000;
203 time_t t0, t1;
204
205 if (!PyArg_ParseTuple(args, "OS|i", &obj, &name, &n))
206 return NULL;
207 t0 = clock();
208 while (--n >= 0) {
209 res = PyObject_GetAttr(obj, name);
210 if (res == NULL)
211 return NULL;
212 Py_DECREF(res);
213 }
214 t1 = clock();
215 return PyFloat_FromDouble((double)(t1-t0) / CLOCKS_PER_SEC);
216}
217
218static PyMethodDef xxsubtype_functions[] = {
219 {"bench", spam_bench, METH_VARARGS},
220 {NULL, NULL} /* sentinel */
221};
222
223DL_EXPORT(void)
224initxxsubtype(void)
225{
226 PyObject *m, *d;
227
228 m = Py_InitModule("xxsubtype", xxsubtype_functions);
229 if (m == NULL)
230 return;
231
Guido van Rossum528b7eb2001-08-07 17:24:28 +0000232 if (PyType_Ready(&spamlist_type) < 0)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000233 return;
Guido van Rossum528b7eb2001-08-07 17:24:28 +0000234 if (PyType_Ready(&spamdict_type) < 0)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000235 return;
236
237 d = PyModule_GetDict(m);
238 if (d == NULL)
239 return;
240
241 Py_INCREF(&spamlist_type);
242 if (PyDict_SetItemString(d, "spamlist",
243 (PyObject *) &spamlist_type) < 0)
244 return;
245
246 Py_INCREF(&spamdict_type);
247 if (PyDict_SetItemString(d, "spamdict",
248 (PyObject *) &spamdict_type) < 0)
249 return;
250}