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