1
2 /* Use this file as a template to start implementing a module that
3 also declares object types. All occurrences of 'Xxo' should be changed
4 to something reasonable for your objects. After that, all other
5 occurrences of 'xx' should be changed to something reasonable for your
6 module. If your module is named foo your sourcefile should be named
7 foomodule.c.
8
9 You will probably want to delete all references to 'x_attr' and add
10 your own types of attributes instead. Maybe you want to name your
11 local variables other than 'self'. If your object type is needed in
12 other files, you'll have to create a file "foobarobject.h"; see
13 floatobject.h for an example. */
14
15 /* Xxo objects */
16
17 #include "Python.h"
18
19 static PyObject *ErrorObject;
20
21 typedef struct {
22 PyObject_HEAD
23 PyObject *x_attr; /* Attributes dictionary */
24 } XxoObject;
25
26 static PyTypeObject Xxo_Type;
27
28 #define XxoObject_Check(v) Py_IS_TYPE(v, &Xxo_Type)
29
30 static XxoObject *
newXxoObject(PyObject * arg)31 newXxoObject(PyObject *arg)
32 {
33 XxoObject *self;
34 self = PyObject_New(XxoObject, &Xxo_Type);
35 if (self == NULL)
36 return NULL;
37 self->x_attr = NULL;
38 return self;
39 }
40
41 /* Xxo methods */
42
43 static void
Xxo_dealloc(XxoObject * self)44 Xxo_dealloc(XxoObject *self)
45 {
46 Py_XDECREF(self->x_attr);
47 PyObject_Free(self);
48 }
49
50 static PyObject *
Xxo_demo(XxoObject * self,PyObject * args)51 Xxo_demo(XxoObject *self, PyObject *args)
52 {
53 if (!PyArg_ParseTuple(args, ":demo"))
54 return NULL;
55 return Py_NewRef(Py_None);
56 }
57
58 static PyMethodDef Xxo_methods[] = {
59 {"demo", (PyCFunction)Xxo_demo, METH_VARARGS,
60 PyDoc_STR("demo() -> None")},
61 {NULL, NULL} /* sentinel */
62 };
63
64 static PyObject *
Xxo_getattro(XxoObject * self,PyObject * name)65 Xxo_getattro(XxoObject *self, PyObject *name)
66 {
67 if (self->x_attr != NULL) {
68 PyObject *v = PyDict_GetItemWithError(self->x_attr, name);
69 if (v != NULL) {
70 return Py_NewRef(v);
71 }
72 else if (PyErr_Occurred()) {
73 return NULL;
74 }
75 }
76 return PyObject_GenericGetAttr((PyObject *)self, name);
77 }
78
79 static int
Xxo_setattr(XxoObject * self,const char * name,PyObject * v)80 Xxo_setattr(XxoObject *self, const char *name, PyObject *v)
81 {
82 if (self->x_attr == NULL) {
83 self->x_attr = PyDict_New();
84 if (self->x_attr == NULL)
85 return -1;
86 }
87 if (v == NULL) {
88 int rv = PyDict_DelItemString(self->x_attr, name);
89 if (rv < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
90 PyErr_SetString(PyExc_AttributeError,
91 "delete non-existing Xxo attribute");
92 return rv;
93 }
94 else
95 return PyDict_SetItemString(self->x_attr, name, v);
96 }
97
98 static PyTypeObject Xxo_Type = {
99 /* The ob_type field must be initialized in the module init function
100 * to be portable to Windows without using C++. */
101 PyVarObject_HEAD_INIT(NULL, 0)
102 "xxmodule.Xxo", /*tp_name*/
103 sizeof(XxoObject), /*tp_basicsize*/
104 0, /*tp_itemsize*/
105 /* methods */
106 (destructor)Xxo_dealloc, /*tp_dealloc*/
107 0, /*tp_vectorcall_offset*/
108 (getattrfunc)0, /*tp_getattr*/
109 (setattrfunc)Xxo_setattr, /*tp_setattr*/
110 0, /*tp_as_async*/
111 0, /*tp_repr*/
112 0, /*tp_as_number*/
113 0, /*tp_as_sequence*/
114 0, /*tp_as_mapping*/
115 0, /*tp_hash*/
116 0, /*tp_call*/
117 0, /*tp_str*/
118 (getattrofunc)Xxo_getattro, /*tp_getattro*/
119 0, /*tp_setattro*/
120 0, /*tp_as_buffer*/
121 Py_TPFLAGS_DEFAULT, /*tp_flags*/
122 0, /*tp_doc*/
123 0, /*tp_traverse*/
124 0, /*tp_clear*/
125 0, /*tp_richcompare*/
126 0, /*tp_weaklistoffset*/
127 0, /*tp_iter*/
128 0, /*tp_iternext*/
129 Xxo_methods, /*tp_methods*/
130 0, /*tp_members*/
131 0, /*tp_getset*/
132 0, /*tp_base*/
133 0, /*tp_dict*/
134 0, /*tp_descr_get*/
135 0, /*tp_descr_set*/
136 0, /*tp_dictoffset*/
137 0, /*tp_init*/
138 0, /*tp_alloc*/
139 0, /*tp_new*/
140 0, /*tp_free*/
141 0, /*tp_is_gc*/
142 };
143 /* --------------------------------------------------------------------- */
144
145 /* Function of two integers returning integer */
146
147 PyDoc_STRVAR(xx_foo_doc,
148 "foo(i,j)\n\
149 \n\
150 Return the sum of i and j.");
151
152 static PyObject *
xx_foo(PyObject * self,PyObject * args)153 xx_foo(PyObject *self, PyObject *args)
154 {
155 long i, j;
156 long res;
157 if (!PyArg_ParseTuple(args, "ll:foo", &i, &j))
158 return NULL;
159 res = i+j; /* XXX Do something here */
160 return PyLong_FromLong(res);
161 }
162
163
164 /* Function of no arguments returning new Xxo object */
165
166 static PyObject *
xx_new(PyObject * self,PyObject * args)167 xx_new(PyObject *self, PyObject *args)
168 {
169 XxoObject *rv;
170
171 if (!PyArg_ParseTuple(args, ":new"))
172 return NULL;
173 rv = newXxoObject(args);
174 if (rv == NULL)
175 return NULL;
176 return (PyObject *)rv;
177 }
178
179 /* Example with subtle bug from extensions manual ("Thin Ice"). */
180
181 static PyObject *
xx_bug(PyObject * self,PyObject * args)182 xx_bug(PyObject *self, PyObject *args)
183 {
184 PyObject *list, *item;
185
186 if (!PyArg_ParseTuple(args, "O:bug", &list))
187 return NULL;
188
189 item = PyList_GetItem(list, 0);
190 /* Py_INCREF(item); */
191 PyList_SetItem(list, 1, PyLong_FromLong(0L));
192 PyObject_Print(item, stdout, 0);
193 printf("\n");
194 /* Py_DECREF(item); */
195
196 return Py_NewRef(Py_None);
197 }
198
199 /* Test bad format character */
200
201 static PyObject *
xx_roj(PyObject * self,PyObject * args)202 xx_roj(PyObject *self, PyObject *args)
203 {
204 PyObject *a;
205 long b;
206 if (!PyArg_ParseTuple(args, "O#:roj", &a, &b))
207 return NULL;
208 return Py_NewRef(Py_None);
209 }
210
211
212 /* ---------- */
213
214 static PyTypeObject Str_Type = {
215 /* The ob_type field must be initialized in the module init function
216 * to be portable to Windows without using C++. */
217 PyVarObject_HEAD_INIT(NULL, 0)
218 "xxmodule.Str", /*tp_name*/
219 0, /*tp_basicsize*/
220 0, /*tp_itemsize*/
221 /* methods */
222 0, /*tp_dealloc*/
223 0, /*tp_vectorcall_offset*/
224 0, /*tp_getattr*/
225 0, /*tp_setattr*/
226 0, /*tp_as_async*/
227 0, /*tp_repr*/
228 0, /*tp_as_number*/
229 0, /*tp_as_sequence*/
230 0, /*tp_as_mapping*/
231 0, /*tp_hash*/
232 0, /*tp_call*/
233 0, /*tp_str*/
234 0, /*tp_getattro*/
235 0, /*tp_setattro*/
236 0, /*tp_as_buffer*/
237 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
238 0, /*tp_doc*/
239 0, /*tp_traverse*/
240 0, /*tp_clear*/
241 0, /*tp_richcompare*/
242 0, /*tp_weaklistoffset*/
243 0, /*tp_iter*/
244 0, /*tp_iternext*/
245 0, /*tp_methods*/
246 0, /*tp_members*/
247 0, /*tp_getset*/
248 0, /* see PyInit_xx */ /*tp_base*/
249 0, /*tp_dict*/
250 0, /*tp_descr_get*/
251 0, /*tp_descr_set*/
252 0, /*tp_dictoffset*/
253 0, /*tp_init*/
254 0, /*tp_alloc*/
255 0, /*tp_new*/
256 0, /*tp_free*/
257 0, /*tp_is_gc*/
258 };
259
260 /* ---------- */
261
262 static PyObject *
null_richcompare(PyObject * self,PyObject * other,int op)263 null_richcompare(PyObject *self, PyObject *other, int op)
264 {
265 return Py_NewRef(Py_NotImplemented);
266 }
267
268 static PyTypeObject Null_Type = {
269 /* The ob_type field must be initialized in the module init function
270 * to be portable to Windows without using C++. */
271 PyVarObject_HEAD_INIT(NULL, 0)
272 "xxmodule.Null", /*tp_name*/
273 0, /*tp_basicsize*/
274 0, /*tp_itemsize*/
275 /* methods */
276 0, /*tp_dealloc*/
277 0, /*tp_vectorcall_offset*/
278 0, /*tp_getattr*/
279 0, /*tp_setattr*/
280 0, /*tp_as_async*/
281 0, /*tp_repr*/
282 0, /*tp_as_number*/
283 0, /*tp_as_sequence*/
284 0, /*tp_as_mapping*/
285 0, /*tp_hash*/
286 0, /*tp_call*/
287 0, /*tp_str*/
288 0, /*tp_getattro*/
289 0, /*tp_setattro*/
290 0, /*tp_as_buffer*/
291 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
292 0, /*tp_doc*/
293 0, /*tp_traverse*/
294 0, /*tp_clear*/
295 null_richcompare, /*tp_richcompare*/
296 0, /*tp_weaklistoffset*/
297 0, /*tp_iter*/
298 0, /*tp_iternext*/
299 0, /*tp_methods*/
300 0, /*tp_members*/
301 0, /*tp_getset*/
302 0, /* see PyInit_xx */ /*tp_base*/
303 0, /*tp_dict*/
304 0, /*tp_descr_get*/
305 0, /*tp_descr_set*/
306 0, /*tp_dictoffset*/
307 0, /*tp_init*/
308 0, /*tp_alloc*/
309 PyType_GenericNew, /*tp_new*/
310 0, /*tp_free*/
311 0, /*tp_is_gc*/
312 };
313
314
315 /* ---------- */
316
317
318 /* List of functions defined in the module */
319
320 static PyMethodDef xx_methods[] = {
321 {"roj", xx_roj, METH_VARARGS,
322 PyDoc_STR("roj(a,b) -> None")},
323 {"foo", xx_foo, METH_VARARGS,
324 xx_foo_doc},
325 {"new", xx_new, METH_VARARGS,
326 PyDoc_STR("new() -> new Xx object")},
327 {"bug", xx_bug, METH_VARARGS,
328 PyDoc_STR("bug(o) -> None")},
329 {NULL, NULL} /* sentinel */
330 };
331
332 PyDoc_STRVAR(module_doc,
333 "This is a template module just for instruction.");
334
335
336 static int
xx_exec(PyObject * m)337 xx_exec(PyObject *m)
338 {
339 /* Slot initialization is subject to the rules of initializing globals.
340 C99 requires the initializers to be "address constants". Function
341 designators like 'PyType_GenericNew', with implicit conversion to
342 a pointer, are valid C99 address constants.
343
344 However, the unary '&' operator applied to a non-static variable
345 like 'PyBaseObject_Type' is not required to produce an address
346 constant. Compilers may support this (gcc does), MSVC does not.
347
348 Both compilers are strictly standard conforming in this particular
349 behavior.
350 */
351 Null_Type.tp_base = &PyBaseObject_Type;
352 Str_Type.tp_base = &PyUnicode_Type;
353
354 /* Finalize the type object including setting type of the new type
355 * object; doing it here is required for portability, too. */
356 if (PyType_Ready(&Xxo_Type) < 0) {
357 return -1;
358 }
359
360 /* Add some symbolic constants to the module */
361 if (ErrorObject == NULL) {
362 ErrorObject = PyErr_NewException("xx.error", NULL, NULL);
363 if (ErrorObject == NULL) {
364 return -1;
365 }
366 }
367 int rc = PyModule_AddType(m, (PyTypeObject *)ErrorObject);
368 Py_DECREF(ErrorObject);
369 if (rc < 0) {
370 return -1;
371 }
372
373 /* Add Str and Null types */
374 if (PyModule_AddType(m, &Str_Type) < 0) {
375 return -1;
376 }
377 if (PyModule_AddType(m, &Null_Type) < 0) {
378 return -1;
379 }
380
381 return 0;
382 }
383
384 static struct PyModuleDef_Slot xx_slots[] = {
385 {Py_mod_exec, xx_exec},
386 {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
387 {Py_mod_gil, Py_MOD_GIL_NOT_USED},
388 {0, NULL},
389 };
390
391 static struct PyModuleDef xxmodule = {
392 PyModuleDef_HEAD_INIT,
393 "xx",
394 module_doc,
395 0,
396 xx_methods,
397 xx_slots,
398 NULL,
399 NULL,
400 NULL
401 };
402
403 /* Export function for the module (*must* be called PyInit_xx) */
404
405 PyMODINIT_FUNC
PyInit_xx(void)406 PyInit_xx(void)
407 {
408 return PyModuleDef_Init(&xxmodule);
409 }
410