diff --git a/Modules/xxmodule.c b/Modules/xxmodule.c --- a/Modules/xxmodule.c +++ b/Modules/xxmodule.c @@ -16,22 +16,59 @@ #include "Python.h" -static PyObject *ErrorObject; +typedef struct { + PyObject *ErrorObject; + PyObject *Xxo_Type; + PyObject *Str_Type; + PyObject *Null_Type; +} xxstate; + + +#define xx_state(o) ((xxstate *)PyModule_GetState(o)) + +static int +xx_clear(PyObject *m) +{ + Py_CLEAR(xx_state(m)->ErrorObject); + Py_CLEAR(xx_state(m)->Xxo_Type); + Py_CLEAR(xx_state(m)->Str_Type); + Py_CLEAR(xx_state(m)->Null_Type); + return 0; +} + +static int +xx_traverse(PyObject *m, visitproc visit, void *arg) +{ + Py_VISIT(xx_state(m)->ErrorObject); + Py_VISIT(xx_state(m)->Xxo_Type); + Py_VISIT(xx_state(m)->Str_Type); + Py_VISIT(xx_state(m)->Null_Type); + return 0; +} + +static void +xx_free(void *m) +{ + xx_clear((PyObject *)m); +} + +static PyModuleDef xxmodule; + +#define xx_state_global ((xxstate *)PyModule_GetState(PyState_FindModule(&xxmodule))) + typedef struct { PyObject_HEAD - PyObject *x_attr; /* Attributes dictionary */ + PyObject *x_attr; /* Attributes dictionary */ } XxoObject; -static PyTypeObject Xxo_Type; - -#define XxoObject_Check(v) (Py_TYPE(v) == &Xxo_Type) +#define XxoObject_Check(v) (Py_TYPE(v) == (PyTypeObject *)xx_state_global->Xxo_Type) static XxoObject * newXxoObject(PyObject *arg) { XxoObject *self; - self = PyObject_New(XxoObject, &Xxo_Type); + self = PyObject_New(XxoObject, (PyTypeObject *)xx_state_global->Xxo_Type); if (self == NULL) return NULL; self->x_attr = NULL; @@ -94,51 +131,22 @@ return PyDict_SetItemString(self->x_attr, name, v); } -static PyTypeObject Xxo_Type = { - /* The ob_type field must be initialized in the module init function - * to be portable to Windows without using C++. */ - PyVarObject_HEAD_INIT(NULL, 0) - "xxmodule.Xxo", /*tp_name*/ - sizeof(XxoObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)Xxo_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)0, /*tp_getattr*/ - (setattrfunc)Xxo_setattr, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - (getattrofunc)Xxo_getattro, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - Xxo_methods, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ - 0, /*tp_alloc*/ - 0, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ +static PyType_Slot Xxo_Type_slots[] = { + {Py_tp_dealloc, (destructor)Xxo_dealloc}, + {Py_tp_setattr, (setattrfunc)Xxo_setattr}, + {Py_tp_getattro, (getattrofunc)Xxo_getattro}, + {Py_tp_methods, Xxo_methods}, + {0, 0} }; + +static PyType_Spec Xxo_Type_spec = { + "xxmodule.Xxo", + sizeof(XxoObject), + 0, + Py_TPFLAGS_DEFAULT, + Xxo_Type_slots, +}; + /* --------------------------------------------------------------------- */ /* Function of two integers returning integer */ @@ -212,52 +220,20 @@ /* ---------- */ -static PyTypeObject Str_Type = { - /* The ob_type field must be initialized in the module init function - * to be portable to Windows without using C++. */ - PyVarObject_HEAD_INIT(NULL, 0) - "xxmodule.Str", /*tp_name*/ - 0, /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ - 0, /* see PyInit_xx */ /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ - 0, /*tp_alloc*/ - 0, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ +static PyType_Slot Str_Type_slots[] = { + {Py_tp_base, }, + {0, 0} }; +static PyType_Spec Str_Type_spec = { + "xxmodule.Str", + 0, + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + Str_Type_slots, +}; + + /* ---------- */ static PyObject * @@ -267,52 +243,22 @@ return Py_NotImplemented; } -static PyTypeObject Null_Type = { - /* The ob_type field must be initialized in the module init function - * to be portable to Windows without using C++. */ - PyVarObject_HEAD_INIT(NULL, 0) - "xxmodule.Null", /*tp_name*/ - 0, /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - null_richcompare, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ - 0, /* see PyInit_xx */ /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ - 0, /*tp_alloc*/ - 0, /* see PyInit_xx */ /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ +static PyType_Slot Null_Type_slots[] = { + {Py_tp_base, }, + {Py_tp_new, }, + {Py_tp_richcompare, null_richcompare}, + {0, 0} }; +static PyType_Spec Null_Type_spec = { + "xxmodule.Null", + 0, + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + Null_Type_slots, +}; + + /* ---------- */ @@ -339,56 +285,66 @@ static struct PyModuleDef xxmodule = { PyModuleDef_HEAD_INIT, - "xx", - module_doc, - -1, - xx_methods, - NULL, - NULL, - NULL, - NULL + "xx", /* m_name */ + module_doc, /* m_doc */ + sizeof(xxstate), /* m_size */ + xx_methods, /* m_methods */ + NULL, /* m_reload */ + xx_traverse, /* m_traverse */ + xx_clear, /* m_clear */ + xx_free, /* m_free */ }; PyMODINIT_FUNC PyInit_xx(void) { - PyObject *m = NULL; - - /* Due to cross platform compiler issues the slots must be filled - * here. It's required for portability to Windows without requiring - * C++. */ - Null_Type.tp_base = &PyBaseObject_Type; - Null_Type.tp_new = PyType_GenericNew; - Str_Type.tp_base = &PyUnicode_Type; - - /* Finalize the type object including setting type of the new type - * object; doing it here is required for portability, too. */ - if (PyType_Ready(&Xxo_Type) < 0) - goto fail; + PyObject *m; /* Create the module and add the functions */ m = PyModule_Create(&xxmodule); if (m == NULL) goto fail; + /* 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; /* Py_tp_bases */ + Null_Type_slots[1].pfunc = PyType_GenericNew; /* Py_tp_new */ + Str_Type_slots[0].pfunc = &PyUnicode_Type; /* Py_tp_bases */ + + /* Finalize the type object including setting type of the new type + * object; doing it here is required for portability, too. */ + + + xx_state(m)->Xxo_Type = PyType_FromSpec(&Xxo_Type_spec); + if (xx_state(m)->Xxo_Type == NULL) + goto fail; + + /* Add some symbolic constants to the module */ - if (ErrorObject == NULL) { - ErrorObject = PyErr_NewException("xx.error", NULL, NULL); - if (ErrorObject == NULL) + if (xx_state(m)->ErrorObject == NULL) { + xx_state(m)->ErrorObject = PyErr_NewException("xx.error", NULL, NULL); + if (xx_state(m)->ErrorObject == NULL) goto fail; } - Py_INCREF(ErrorObject); - PyModule_AddObject(m, "error", ErrorObject); + Py_INCREF(xx_state(m)->ErrorObject); + PyModule_AddObject(m, "error", xx_state(m)->ErrorObject); + + /* Add Null */ + xx_state(m)->Null_Type = PyType_FromSpec(&Null_Type_spec); + if (xx_state(m)->Null_Type == NULL) + goto fail; + Py_INCREF(xx_state(m)->Null_Type); + PyModule_AddObject(m, "Null", xx_state(m)->Null_Type); /* Add Str */ - if (PyType_Ready(&Str_Type) < 0) + xx_state(m)->Str_Type = PyType_FromSpec(&Str_Type_spec); + if (xx_state(m)->Str_Type == NULL) goto fail; - PyModule_AddObject(m, "Str", (PyObject *)&Str_Type); - - /* Add Null */ - if (PyType_Ready(&Null_Type) < 0) - goto fail; - PyModule_AddObject(m, "Null", (PyObject *)&Null_Type); + Py_INCREF(xx_state(m)->Str_Type); + PyModule_AddObject(m, "Str", xx_state(m)->Str_Type); + return m; fail: Py_XDECREF(m);