diff -r 4bbac0b8de1b Modules/xxmodule.c --- a/Modules/xxmodule.c Fri Aug 31 13:54:47 2012 +0200 +++ b/Modules/xxmodule.c Sun Sep 02 16:30:57 2012 +0200 @@ -16,22 +16,61 @@ #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 */ } 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 +133,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 +222,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_bases, }, + {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 +245,20 @@ 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_richcompare, null_richcompare}, + {0, 0} }; +static PyType_Spec Null_Type_spec = { + "xxmodule.Null", + 0, + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + Null_Type_slots, +}; + + /* ---------- */ @@ -341,54 +287,57 @@ PyModuleDef_HEAD_INIT, "xx", module_doc, - -1, - xx_methods, + sizeof(xxstate), + xx_methods, NULL, - NULL, - NULL, - NULL + xx_traverse, + xx_clear, + xx_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++. */ + (PyTypeObject *)xx_state(m)->Null_Type)->tp_base = &PyBaseObject_Type; + (PyTypeObject *)xx_state(m)->Null_Type)->tp_new = PyType_GenericNew; + (PyTypeObject *)xx_state(m)->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. */ + 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 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); + PyModule_AddObject(m, "Str", xx_state(m)->Str_Type); /* Add Null */ - if (PyType_Ready(&Null_Type) < 0) + xx_state(m)->Null_Type = PyType_FromSpec(&Null_Type_spec); + if (xx_state(m)->Null_Type == NULL) goto fail; - PyModule_AddObject(m, "Null", (PyObject *)&Null_Type); + PyModule_AddObject(m, "Null", xx_state(m)->Null_Type); return m; fail: Py_XDECREF(m);