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