Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 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 |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 6 | module. If your module is named foo your source file should be named |
| 7 | foo.c or foomodule.c. |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 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 |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 13 | floatobject.h for an example. |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 14 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 15 | This module roughly corresponds to:: |
| 16 | |
| 17 | class Xxo: |
| 18 | """A class that explicitly stores attributes in an internal dict""" |
| 19 | |
| 20 | def __init__(self): |
| 21 | # In the C class, "_x_attr" is not accessible from Python code |
| 22 | self._x_attr = {} |
| 23 | |
| 24 | def __getattr__(self, name): |
| 25 | return self._x_attr[name] |
| 26 | |
| 27 | def __setattr__(self, name, value): |
| 28 | self._x_attr[name] = value |
| 29 | |
| 30 | def __delattr__(self, name): |
| 31 | del self._x_attr[name] |
| 32 | |
| 33 | def demo(o, /): |
| 34 | if isinstance(o, str): |
| 35 | return o |
| 36 | elif isinstance(o, Xxo): |
| 37 | return o |
| 38 | else: |
| 39 | raise Error('argument must be str or Xxo') |
| 40 | |
| 41 | class Error(Exception): |
| 42 | """Exception raised by the xxlimited module""" |
| 43 | |
| 44 | def foo(i: int, j: int, /): |
| 45 | """Return the sum of i and j.""" |
| 46 | # Unlike this pseudocode, the C function will *only* work with |
| 47 | # integers and perform C long int arithmetic |
| 48 | return i + j |
| 49 | |
| 50 | def new(): |
| 51 | return Xxo() |
| 52 | |
| 53 | def Str(str): |
| 54 | # A trivial subclass of a built-in type |
| 55 | pass |
| 56 | */ |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 57 | |
| 58 | #include "Python.h" |
| 59 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 60 | // Module state |
| 61 | typedef struct { |
| 62 | PyObject *Xxo_Type; // Xxo class |
| 63 | PyObject *Error_Type; // Error class |
| 64 | } xx_state; |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 65 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 66 | |
| 67 | /* Xxo objects */ |
| 68 | |
| 69 | // Instance state |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 70 | typedef struct { |
| 71 | PyObject_HEAD |
| 72 | PyObject *x_attr; /* Attributes dictionary */ |
| 73 | } XxoObject; |
| 74 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 75 | // XXX: no good way to do this yet |
| 76 | // #define XxoObject_Check(v) Py_IS_TYPE(v, Xxo_Type) |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 77 | |
| 78 | static XxoObject * |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 79 | newXxoObject(PyObject *module) |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 80 | { |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 81 | xx_state *state = PyModule_GetState(module); |
| 82 | if (state == NULL) { |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 83 | return NULL; |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 84 | } |
| 85 | XxoObject *self; |
| 86 | self = PyObject_GC_New(XxoObject, (PyTypeObject*)state->Xxo_Type); |
| 87 | if (self == NULL) { |
| 88 | return NULL; |
| 89 | } |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 90 | self->x_attr = NULL; |
| 91 | return self; |
| 92 | } |
| 93 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 94 | /* Xxo finalization */ |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 95 | |
Nick Coghlan | 53f9502 | 2015-06-04 21:52:57 +1000 | [diff] [blame] | 96 | static int |
| 97 | Xxo_traverse(XxoObject *self, visitproc visit, void *arg) |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 98 | { |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 99 | // Visit the type |
Pablo Galindo | 1cf15af | 2020-05-27 10:03:38 +0100 | [diff] [blame] | 100 | Py_VISIT(Py_TYPE(self)); |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 101 | |
| 102 | // Visit the attribute dict |
Nick Coghlan | 53f9502 | 2015-06-04 21:52:57 +1000 | [diff] [blame] | 103 | Py_VISIT(self->x_attr); |
| 104 | return 0; |
| 105 | } |
| 106 | |
Serhiy Storchaka | 19de8b3 | 2018-05-26 10:51:58 +0300 | [diff] [blame] | 107 | static void |
Nick Coghlan | 53f9502 | 2015-06-04 21:52:57 +1000 | [diff] [blame] | 108 | Xxo_finalize(XxoObject *self) |
| 109 | { |
| 110 | Py_CLEAR(self->x_attr); |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 111 | } |
| 112 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 113 | static void |
| 114 | Xxo_dealloc(XxoObject *self) |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 115 | { |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 116 | Xxo_finalize(self); |
| 117 | PyTypeObject *tp = Py_TYPE(self); |
| 118 | freefunc free = PyType_GetSlot(tp, Py_tp_free); |
| 119 | free(self); |
| 120 | Py_DECREF(tp); |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 121 | } |
| 122 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 123 | |
| 124 | /* Xxo attribute handling */ |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 125 | |
| 126 | static PyObject * |
| 127 | Xxo_getattro(XxoObject *self, PyObject *name) |
| 128 | { |
| 129 | if (self->x_attr != NULL) { |
Serhiy Storchaka | a24107b | 2019-02-25 17:59:46 +0200 | [diff] [blame] | 130 | PyObject *v = PyDict_GetItemWithError(self->x_attr, name); |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 131 | if (v != NULL) { |
| 132 | Py_INCREF(v); |
| 133 | return v; |
| 134 | } |
Serhiy Storchaka | a24107b | 2019-02-25 17:59:46 +0200 | [diff] [blame] | 135 | else if (PyErr_Occurred()) { |
| 136 | return NULL; |
| 137 | } |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 138 | } |
| 139 | return PyObject_GenericGetAttr((PyObject *)self, name); |
| 140 | } |
| 141 | |
| 142 | static int |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 143 | Xxo_setattro(XxoObject *self, PyObject *name, PyObject *v) |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 144 | { |
| 145 | if (self->x_attr == NULL) { |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 146 | // prepare the attribute dict |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 147 | self->x_attr = PyDict_New(); |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 148 | if (self->x_attr == NULL) { |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 149 | return -1; |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 150 | } |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 151 | } |
| 152 | if (v == NULL) { |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 153 | // delete an attribute |
| 154 | int rv = PyDict_DelItem(self->x_attr, name); |
| 155 | if (rv < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) { |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 156 | PyErr_SetString(PyExc_AttributeError, |
| 157 | "delete non-existing Xxo attribute"); |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 158 | return -1; |
| 159 | } |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 160 | return rv; |
| 161 | } |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 162 | else { |
| 163 | // set an attribute |
| 164 | return PyDict_SetItem(self->x_attr, name, v); |
| 165 | } |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 166 | } |
| 167 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 168 | /* Xxo methods */ |
| 169 | |
| 170 | static PyObject * |
| 171 | Xxo_demo(XxoObject *self, PyTypeObject *defining_class, |
| 172 | PyObject **args, Py_ssize_t nargs, PyObject *kwnames) |
| 173 | { |
| 174 | if (kwnames != NULL && PyObject_Length(kwnames)) { |
| 175 | PyErr_SetString(PyExc_TypeError, "demo() takes no keyword arguments"); |
| 176 | return NULL; |
| 177 | } |
| 178 | if (nargs != 1) { |
| 179 | PyErr_SetString(PyExc_TypeError, "demo() takes exactly 1 argument"); |
| 180 | return NULL; |
| 181 | } |
| 182 | |
| 183 | PyObject *o = args[0]; |
| 184 | |
| 185 | /* Test if the argument is "str" */ |
| 186 | if (PyUnicode_Check(o)) { |
| 187 | Py_INCREF(o); |
| 188 | return o; |
| 189 | } |
| 190 | |
| 191 | /* test if the argument is of the Xxo class */ |
| 192 | if (PyObject_TypeCheck(o, defining_class)) { |
| 193 | Py_INCREF(o); |
| 194 | return o; |
| 195 | } |
| 196 | |
| 197 | Py_INCREF(Py_None); |
| 198 | return Py_None; |
| 199 | } |
| 200 | |
| 201 | static PyMethodDef Xxo_methods[] = { |
| 202 | {"demo", (PyCFunction)(void(*)(void))Xxo_demo, |
| 203 | METH_METHOD | METH_FASTCALL | METH_KEYWORDS, PyDoc_STR("demo(o) -> o")}, |
| 204 | {NULL, NULL} /* sentinel */ |
| 205 | }; |
| 206 | |
| 207 | /* Xxo type definition */ |
| 208 | |
| 209 | PyDoc_STRVAR(Xxo_doc, |
| 210 | "A class that explicitly stores attributes in an internal dict"); |
| 211 | |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 212 | static PyType_Slot Xxo_Type_slots[] = { |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 213 | {Py_tp_doc, (char *)Xxo_doc}, |
Nick Coghlan | 53f9502 | 2015-06-04 21:52:57 +1000 | [diff] [blame] | 214 | {Py_tp_traverse, Xxo_traverse}, |
| 215 | {Py_tp_finalize, Xxo_finalize}, |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 216 | {Py_tp_dealloc, Xxo_dealloc}, |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 217 | {Py_tp_getattro, Xxo_getattro}, |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 218 | {Py_tp_setattro, Xxo_setattro}, |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 219 | {Py_tp_methods, Xxo_methods}, |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 220 | {0, 0}, /* sentinel */ |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 221 | }; |
| 222 | |
| 223 | static PyType_Spec Xxo_Type_spec = { |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 224 | .name = "xxlimited.Xxo", |
| 225 | .basicsize = sizeof(XxoObject), |
| 226 | .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, |
| 227 | .slots = Xxo_Type_slots, |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 228 | }; |
| 229 | |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 230 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 231 | /* Str type definition*/ |
| 232 | |
| 233 | static PyType_Slot Str_Type_slots[] = { |
| 234 | {0, 0}, /* sentinel */ |
| 235 | }; |
| 236 | |
| 237 | static PyType_Spec Str_Type_spec = { |
| 238 | .name = "xxlimited.Str", |
| 239 | .basicsize = 0, |
| 240 | .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, |
| 241 | .slots = Str_Type_slots, |
| 242 | }; |
| 243 | |
| 244 | |
| 245 | /* Function of two integers returning integer (with C "long int" arithmetic) */ |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 246 | |
| 247 | PyDoc_STRVAR(xx_foo_doc, |
| 248 | "foo(i,j)\n\ |
| 249 | \n\ |
| 250 | Return the sum of i and j."); |
| 251 | |
| 252 | static PyObject * |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 253 | xx_foo(PyObject *module, PyObject *args) |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 254 | { |
| 255 | long i, j; |
| 256 | long res; |
| 257 | if (!PyArg_ParseTuple(args, "ll:foo", &i, &j)) |
| 258 | return NULL; |
| 259 | res = i+j; /* XXX Do something here */ |
| 260 | return PyLong_FromLong(res); |
| 261 | } |
| 262 | |
| 263 | |
| 264 | /* Function of no arguments returning new Xxo object */ |
| 265 | |
| 266 | static PyObject * |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 267 | xx_new(PyObject *module, PyObject *Py_UNUSED(unused)) |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 268 | { |
| 269 | XxoObject *rv; |
| 270 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 271 | rv = newXxoObject(module); |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 272 | if (rv == NULL) |
| 273 | return NULL; |
| 274 | return (PyObject *)rv; |
| 275 | } |
| 276 | |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 277 | |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 278 | |
| 279 | /* List of functions defined in the module */ |
| 280 | |
| 281 | static PyMethodDef xx_methods[] = { |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 282 | {"foo", xx_foo, METH_VARARGS, |
| 283 | xx_foo_doc}, |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 284 | {"new", xx_new, METH_NOARGS, |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 285 | PyDoc_STR("new() -> new Xx object")}, |
| 286 | {NULL, NULL} /* sentinel */ |
| 287 | }; |
| 288 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 289 | |
| 290 | /* The module itself */ |
| 291 | |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 292 | PyDoc_STRVAR(module_doc, |
| 293 | "This is a template module just for instruction."); |
| 294 | |
Nick Coghlan | d5cacbb | 2015-05-23 22:24:10 +1000 | [diff] [blame] | 295 | static int |
| 296 | xx_modexec(PyObject *m) |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 297 | { |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 298 | xx_state *state = PyModule_GetState(m); |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 299 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 300 | state->Error_Type = PyErr_NewException("xxlimited.Error", NULL, NULL); |
| 301 | if (state->Error_Type == NULL) { |
| 302 | return -1; |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 303 | } |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 304 | if (PyModule_AddType(m, (PyTypeObject*)state->Error_Type) < 0) { |
| 305 | return -1; |
| 306 | } |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 307 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 308 | state->Xxo_Type = PyType_FromModuleAndSpec(m, &Xxo_Type_spec, NULL); |
| 309 | if (state->Xxo_Type == NULL) { |
| 310 | return -1; |
| 311 | } |
| 312 | if (PyModule_AddType(m, (PyTypeObject*)state->Xxo_Type) < 0) { |
| 313 | return -1; |
| 314 | } |
Nick Coghlan | 53f9502 | 2015-06-04 21:52:57 +1000 | [diff] [blame] | 315 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 316 | // Add the Str type. It is not needed from C code, so it is only |
| 317 | // added to the module dict. |
| 318 | // It does not inherit from "object" (PyObject_Type), but from "str" |
| 319 | // (PyUnincode_Type). |
| 320 | PyObject *Str_Type = PyType_FromModuleAndSpec( |
| 321 | m, &Str_Type_spec, (PyObject *)&PyUnicode_Type); |
| 322 | if (Str_Type == NULL) { |
| 323 | return -1; |
| 324 | } |
| 325 | if (PyModule_AddType(m, (PyTypeObject*)Str_Type) < 0) { |
| 326 | return -1; |
| 327 | } |
| 328 | Py_DECREF(Str_Type); |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 329 | |
Nick Coghlan | d5cacbb | 2015-05-23 22:24:10 +1000 | [diff] [blame] | 330 | return 0; |
Nick Coghlan | d5cacbb | 2015-05-23 22:24:10 +1000 | [diff] [blame] | 331 | } |
| 332 | |
Nick Coghlan | d5cacbb | 2015-05-23 22:24:10 +1000 | [diff] [blame] | 333 | static PyModuleDef_Slot xx_slots[] = { |
| 334 | {Py_mod_exec, xx_modexec}, |
| 335 | {0, NULL} |
| 336 | }; |
| 337 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 338 | static int |
| 339 | xx_traverse(PyObject *module, visitproc visit, void *arg) |
| 340 | { |
| 341 | xx_state *state = PyModule_GetState(module); |
| 342 | Py_VISIT(state->Xxo_Type); |
| 343 | Py_VISIT(state->Error_Type); |
| 344 | return 0; |
| 345 | } |
| 346 | |
| 347 | static int |
| 348 | xx_clear(PyObject *module) |
| 349 | { |
| 350 | xx_state *state = PyModule_GetState(module); |
| 351 | Py_CLEAR(state->Xxo_Type); |
| 352 | Py_CLEAR(state->Error_Type); |
| 353 | return 0; |
| 354 | } |
| 355 | |
Nick Coghlan | d5cacbb | 2015-05-23 22:24:10 +1000 | [diff] [blame] | 356 | static struct PyModuleDef xxmodule = { |
| 357 | PyModuleDef_HEAD_INIT, |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 358 | .m_name = "xxlimited", |
| 359 | .m_doc = module_doc, |
| 360 | .m_size = sizeof(xx_state), |
| 361 | .m_methods = xx_methods, |
| 362 | .m_slots = xx_slots, |
| 363 | .m_traverse = xx_traverse, |
| 364 | .m_clear = xx_clear, |
| 365 | /* m_free is not necessary here: xx_clear clears all references, |
| 366 | * and the module state is deallocated along with the module. |
| 367 | */ |
Nick Coghlan | d5cacbb | 2015-05-23 22:24:10 +1000 | [diff] [blame] | 368 | }; |
| 369 | |
Petr Viktorin | c168b50 | 2020-12-08 17:36:53 +0100 | [diff] [blame] | 370 | |
Nick Coghlan | d5cacbb | 2015-05-23 22:24:10 +1000 | [diff] [blame] | 371 | /* Export function for the module (*must* be called PyInit_xx) */ |
| 372 | |
| 373 | PyMODINIT_FUNC |
| 374 | PyInit_xxlimited(void) |
| 375 | { |
| 376 | return PyModuleDef_Init(&xxmodule); |
Martin v. Löwis | 4d0d471 | 2010-12-03 20:14:31 +0000 | [diff] [blame] | 377 | } |