| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Use this file as a template to start implementing a module that
 | 
					
						
							|  |  |  |    also declares object types. All occurrences of 'Xxo' should be changed | 
					
						
							|  |  |  |    to something reasonable for your objects. After that, all other | 
					
						
							|  |  |  |    occurrences of 'xx' should be changed to something reasonable for your | 
					
						
							|  |  |  |    module. If your module is named foo your sourcefile should be named | 
					
						
							|  |  |  |    foomodule.c. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    You will probably want to delete all references to 'x_attr' and add | 
					
						
							|  |  |  |    your own types of attributes instead.  Maybe you want to name your | 
					
						
							|  |  |  |    local variables other than 'self'.  If your object type is needed in | 
					
						
							|  |  |  |    other files, you'll have to create a file "foobarobject.h"; see | 
					
						
							|  |  |  |    floatobject.h for an example. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Xxo objects */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Python.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *ErrorObject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     PyObject_HEAD | 
					
						
							|  |  |  |     PyObject            *x_attr;        /* Attributes dictionary */ | 
					
						
							|  |  |  | } XxoObject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Xxo_Type; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-17 19:09:15 +09:00
										 |  |  | #define XxoObject_Check(v)      Py_IS_TYPE(v, Xxo_Type)
 | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static XxoObject * | 
					
						
							|  |  |  | newXxoObject(PyObject *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     XxoObject *self; | 
					
						
							| 
									
										
										
										
											2017-01-31 23:31:02 -08:00
										 |  |  |     self = PyObject_GC_New(XxoObject, (PyTypeObject*)Xxo_Type); | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |     if (self == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     self->x_attr = NULL; | 
					
						
							|  |  |  |     return self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Xxo methods */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 21:52:57 +10:00
										 |  |  | static int | 
					
						
							|  |  |  | Xxo_traverse(XxoObject *self, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-28 08:12:23 -07:00
										 |  |  |     Py_VISIT(Py_TYPE(self)); | 
					
						
							| 
									
										
										
										
											2015-06-04 21:52:57 +10:00
										 |  |  |     Py_VISIT(self->x_attr); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-26 10:51:58 +03:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2015-06-04 21:52:57 +10:00
										 |  |  | Xxo_finalize(XxoObject *self) | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-06-04 21:52:57 +10:00
										 |  |  |     Py_CLEAR(self->x_attr); | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | Xxo_demo(XxoObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-05 20:35:29 +00:00
										 |  |  |     PyObject *o = NULL; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "|O:demo", &o)) | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2011-02-05 20:35:29 +00:00
										 |  |  |     /* Test availability of fast type checks */ | 
					
						
							|  |  |  |     if (o != NULL && PyUnicode_Check(o)) { | 
					
						
							|  |  |  |         Py_INCREF(o); | 
					
						
							|  |  |  |         return o; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |     Py_INCREF(Py_None); | 
					
						
							|  |  |  |     return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef Xxo_methods[] = { | 
					
						
							|  |  |  |     {"demo",            (PyCFunction)Xxo_demo,  METH_VARARGS, | 
					
						
							|  |  |  |         PyDoc_STR("demo() -> None")}, | 
					
						
							|  |  |  |     {NULL,              NULL}           /* sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | Xxo_getattro(XxoObject *self, PyObject *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (self->x_attr != NULL) { | 
					
						
							| 
									
										
										
										
											2019-02-25 17:59:46 +02:00
										 |  |  |         PyObject *v = PyDict_GetItemWithError(self->x_attr, name); | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |         if (v != NULL) { | 
					
						
							|  |  |  |             Py_INCREF(v); | 
					
						
							|  |  |  |             return v; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-02-25 17:59:46 +02:00
										 |  |  |         else if (PyErr_Occurred()) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     return PyObject_GenericGetAttr((PyObject *)self, name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2015-12-25 20:01:53 +02:00
										 |  |  | Xxo_setattr(XxoObject *self, const char *name, PyObject *v) | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     if (self->x_attr == NULL) { | 
					
						
							|  |  |  |         self->x_attr = PyDict_New(); | 
					
						
							|  |  |  |         if (self->x_attr == NULL) | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (v == NULL) { | 
					
						
							|  |  |  |         int rv = PyDict_DelItemString(self->x_attr, name); | 
					
						
							| 
									
										
										
										
											2019-02-25 17:59:46 +02:00
										 |  |  |         if (rv < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |             PyErr_SetString(PyExc_AttributeError, | 
					
						
							|  |  |  |                 "delete non-existing Xxo attribute"); | 
					
						
							|  |  |  |         return rv; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return PyDict_SetItemString(self->x_attr, name, v); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyType_Slot Xxo_Type_slots[] = { | 
					
						
							| 
									
										
										
										
											2011-02-11 20:47:49 +00:00
										 |  |  |     {Py_tp_doc, "The Xxo type"}, | 
					
						
							| 
									
										
										
										
											2015-06-04 21:52:57 +10:00
										 |  |  |     {Py_tp_traverse, Xxo_traverse}, | 
					
						
							|  |  |  |     {Py_tp_finalize, Xxo_finalize}, | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |     {Py_tp_getattro, Xxo_getattro}, | 
					
						
							|  |  |  |     {Py_tp_setattr, Xxo_setattr}, | 
					
						
							|  |  |  |     {Py_tp_methods, Xxo_methods}, | 
					
						
							|  |  |  |     {0, 0}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyType_Spec Xxo_Type_spec = { | 
					
						
							| 
									
										
										
										
											2011-02-11 20:47:49 +00:00
										 |  |  |     "xxlimited.Xxo", | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |     sizeof(XxoObject), | 
					
						
							|  |  |  |     0, | 
					
						
							| 
									
										
										
										
											2019-05-29 22:12:38 +02:00
										 |  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |     Xxo_Type_slots | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* --------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Function of two integers returning integer */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(xx_foo_doc, | 
					
						
							|  |  |  | "foo(i,j)\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return the sum of i and j."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | xx_foo(PyObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     long i, j; | 
					
						
							|  |  |  |     long res; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "ll:foo", &i, &j)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     res = i+j; /* XXX Do something here */ | 
					
						
							|  |  |  |     return PyLong_FromLong(res); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Function of no arguments returning new Xxo object */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | xx_new(PyObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     XxoObject *rv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, ":new")) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     rv = newXxoObject(args); | 
					
						
							|  |  |  |     if (rv == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     return (PyObject *)rv; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Test bad format character */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | xx_roj(PyObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *a; | 
					
						
							|  |  |  |     long b; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "O#:roj", &a, &b)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     Py_INCREF(Py_None); | 
					
						
							|  |  |  |     return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-18 21:53:15 +02:00
										 |  |  | static PyType_Slot Str_Type_slots[] = { | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |     {Py_tp_base, NULL}, /* filled out in module init function */ | 
					
						
							|  |  |  |     {0, 0}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyType_Spec Str_Type_spec = { | 
					
						
							|  |  |  |     "xxlimited.Str", | 
					
						
							|  |  |  |     0, | 
					
						
							|  |  |  |     0, | 
					
						
							|  |  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, | 
					
						
							|  |  |  |     Str_Type_slots | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | null_richcompare(PyObject *self, PyObject *other, int op) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-08-10 20:28:54 -05:00
										 |  |  |     Py_RETURN_NOTIMPLEMENTED; | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyType_Slot Null_Type_slots[] = { | 
					
						
							|  |  |  |     {Py_tp_base, NULL}, /* filled out in module init */ | 
					
						
							|  |  |  |     {Py_tp_new, NULL}, | 
					
						
							|  |  |  |     {Py_tp_richcompare, null_richcompare}, | 
					
						
							|  |  |  |     {0, 0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyType_Spec Null_Type_spec = { | 
					
						
							|  |  |  |     "xxlimited.Null", | 
					
						
							|  |  |  |     0,               /* basicsize */ | 
					
						
							|  |  |  |     0,               /* itemsize */ | 
					
						
							|  |  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, | 
					
						
							|  |  |  |     Null_Type_slots | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* List of functions defined in the module */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef xx_methods[] = { | 
					
						
							|  |  |  |     {"roj",             xx_roj,         METH_VARARGS, | 
					
						
							|  |  |  |         PyDoc_STR("roj(a,b) -> None")}, | 
					
						
							|  |  |  |     {"foo",             xx_foo,         METH_VARARGS, | 
					
						
							|  |  |  |         xx_foo_doc}, | 
					
						
							|  |  |  |     {"new",             xx_new,         METH_VARARGS, | 
					
						
							|  |  |  |         PyDoc_STR("new() -> new Xx object")}, | 
					
						
							|  |  |  |     {NULL,              NULL}           /* sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(module_doc, | 
					
						
							|  |  |  | "This is a template module just for instruction."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-23 22:24:10 +10:00
										 |  |  | static int | 
					
						
							|  |  |  | xx_modexec(PyObject *m) | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     PyObject *o; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Due to cross platform compiler issues the slots must be filled
 | 
					
						
							|  |  |  |      * here. It's required for portability to Windows without requiring | 
					
						
							|  |  |  |      * C++. */ | 
					
						
							|  |  |  |     Null_Type_slots[0].pfunc = &PyBaseObject_Type; | 
					
						
							|  |  |  |     Null_Type_slots[1].pfunc = PyType_GenericNew; | 
					
						
							|  |  |  |     Str_Type_slots[0].pfunc = &PyUnicode_Type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Xxo_Type = PyType_FromSpec(&Xxo_Type_spec); | 
					
						
							|  |  |  |     if (Xxo_Type == NULL) | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Add some symbolic constants to the module */ | 
					
						
							|  |  |  |     if (ErrorObject == NULL) { | 
					
						
							| 
									
										
										
										
											2011-02-11 20:47:49 +00:00
										 |  |  |         ErrorObject = PyErr_NewException("xxlimited.error", NULL, NULL); | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |         if (ErrorObject == NULL) | 
					
						
							|  |  |  |             goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_INCREF(ErrorObject); | 
					
						
							|  |  |  |     PyModule_AddObject(m, "error", ErrorObject); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 21:52:57 +10:00
										 |  |  |     /* Add Xxo */ | 
					
						
							|  |  |  |     o = PyType_FromSpec(&Xxo_Type_spec); | 
					
						
							|  |  |  |     if (o == NULL) | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     PyModule_AddObject(m, "Xxo", o); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |     /* Add Str */ | 
					
						
							|  |  |  |     o = PyType_FromSpec(&Str_Type_spec); | 
					
						
							|  |  |  |     if (o == NULL) | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     PyModule_AddObject(m, "Str", o); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Add Null */ | 
					
						
							|  |  |  |     o = PyType_FromSpec(&Null_Type_spec); | 
					
						
							|  |  |  |     if (o == NULL) | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     PyModule_AddObject(m, "Null", o); | 
					
						
							| 
									
										
										
										
											2015-05-23 22:24:10 +10:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |  fail: | 
					
						
							|  |  |  |     Py_XDECREF(m); | 
					
						
							| 
									
										
										
										
											2015-05-23 22:24:10 +10:00
										 |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyModuleDef_Slot xx_slots[] = { | 
					
						
							|  |  |  |     {Py_mod_exec, xx_modexec}, | 
					
						
							|  |  |  |     {0, NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyModuleDef xxmodule = { | 
					
						
							|  |  |  |     PyModuleDef_HEAD_INIT, | 
					
						
							|  |  |  |     "xxlimited", | 
					
						
							|  |  |  |     module_doc, | 
					
						
							|  |  |  |     0, | 
					
						
							|  |  |  |     xx_methods, | 
					
						
							|  |  |  |     xx_slots, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     NULL | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Export function for the module (*must* be called PyInit_xx) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyMODINIT_FUNC | 
					
						
							|  |  |  | PyInit_xxlimited(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return PyModuleDef_Init(&xxmodule); | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  | } |