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