• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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