@@ -126,6 +126,8 @@ bytes(cdata)
126126
127127#include "pycore_long.h" // _PyLong_GetZero()
128128
129+ ctypes_state global_state ;
130+
129131PyObject * PyExc_ArgError = NULL ;
130132
131133/* This dict maps ctypes types to POINTER types */
@@ -150,13 +152,32 @@ typedef struct {
150152 PyObject * dict ;
151153} DictRemoverObject ;
152154
155+ static int
156+ _DictRemover_traverse (DictRemoverObject * self , visitproc visit , void * arg )
157+ {
158+ Py_VISIT (Py_TYPE (self ));
159+ Py_VISIT (self -> key );
160+ Py_VISIT (self -> dict );
161+ return 0 ;
162+ }
163+
164+ static int
165+ _DictRemover_clear (DictRemoverObject * self )
166+ {
167+ Py_CLEAR (self -> key );
168+ Py_CLEAR (self -> dict );
169+ return 0 ;
170+ }
171+
153172static void
154173_DictRemover_dealloc (PyObject * myself )
155174{
175+ PyTypeObject * tp = Py_TYPE (myself );
156176 DictRemoverObject * self = (DictRemoverObject * )myself ;
157- Py_XDECREF (self -> key );
158- Py_XDECREF (self -> dict );
159- Py_TYPE (self )-> tp_free (myself );
177+ PyObject_GC_UnTrack (myself );
178+ (void )_DictRemover_clear (self );
179+ tp -> tp_free (myself );
180+ Py_DECREF (tp );
160181}
161182
162183static PyObject *
@@ -173,47 +194,23 @@ _DictRemover_call(PyObject *myself, PyObject *args, PyObject *kw)
173194 Py_RETURN_NONE ;
174195}
175196
176- static PyTypeObject DictRemover_Type = {
177- PyVarObject_HEAD_INIT (NULL , 0 )
178- "_ctypes.DictRemover" , /* tp_name */
179- sizeof (DictRemoverObject ), /* tp_basicsize */
180- 0 , /* tp_itemsize */
181- _DictRemover_dealloc , /* tp_dealloc */
182- 0 , /* tp_vectorcall_offset */
183- 0 , /* tp_getattr */
184- 0 , /* tp_setattr */
185- 0 , /* tp_as_async */
186- 0 , /* tp_repr */
187- 0 , /* tp_as_number */
188- 0 , /* tp_as_sequence */
189- 0 , /* tp_as_mapping */
190- 0 , /* tp_hash */
191- _DictRemover_call , /* tp_call */
192- 0 , /* tp_str */
193- 0 , /* tp_getattro */
194- 0 , /* tp_setattro */
195- 0 , /* tp_as_buffer */
196- /* XXX should participate in GC? */
197- Py_TPFLAGS_DEFAULT , /* tp_flags */
198- PyDoc_STR ("deletes a key from a dictionary" ), /* tp_doc */
199- 0 , /* tp_traverse */
200- 0 , /* tp_clear */
201- 0 , /* tp_richcompare */
202- 0 , /* tp_weaklistoffset */
203- 0 , /* tp_iter */
204- 0 , /* tp_iternext */
205- 0 , /* tp_methods */
206- 0 , /* tp_members */
207- 0 , /* tp_getset */
208- 0 , /* tp_base */
209- 0 , /* tp_dict */
210- 0 , /* tp_descr_get */
211- 0 , /* tp_descr_set */
212- 0 , /* tp_dictoffset */
213- 0 , /* tp_init */
214- 0 , /* tp_alloc */
215- 0 , /* tp_new */
216- 0 , /* tp_free */
197+ PyDoc_STRVAR (dictremover_doc , "deletes a key from a dictionary" );
198+
199+ static PyType_Slot dictremover_slots [] = {
200+ {Py_tp_dealloc , _DictRemover_dealloc },
201+ {Py_tp_traverse , _DictRemover_traverse },
202+ {Py_tp_clear , _DictRemover_clear },
203+ {Py_tp_call , _DictRemover_call },
204+ {Py_tp_doc , (void * )dictremover_doc },
205+ {0 , NULL },
206+ };
207+
208+ static PyType_Spec dictremover_spec = {
209+ .name = "_ctypes.DictRemover" ,
210+ .basicsize = sizeof (DictRemoverObject ),
211+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
212+ Py_TPFLAGS_IMMUTABLETYPE ),
213+ .slots = dictremover_slots ,
217214};
218215
219216int
@@ -224,7 +221,8 @@ PyDict_SetItemProxy(PyObject *dict, PyObject *key, PyObject *item)
224221 PyObject * proxy ;
225222 int result ;
226223
227- obj = _PyObject_CallNoArgs ((PyObject * )& DictRemover_Type );
224+ ctypes_state * st = GLOBAL_STATE ();
225+ obj = _PyObject_CallNoArgs ((PyObject * )st -> DictRemover_Type );
228226 if (obj == NULL )
229227 return -1 ;
230228
@@ -415,23 +413,45 @@ typedef struct {
415413 PyObject * keep ; // If set, a reference to the original CDataObject.
416414} StructParamObject ;
417415
416+ static int
417+ StructParam_traverse (StructParamObject * self , visitproc visit , void * arg )
418+ {
419+ Py_VISIT (Py_TYPE (self ));
420+ return 0 ;
421+ }
422+
423+ static int
424+ StructParam_clear (StructParamObject * self )
425+ {
426+ Py_CLEAR (self -> keep );
427+ return 0 ;
428+ }
418429
419430static void
420431StructParam_dealloc (PyObject * myself )
421432{
422433 StructParamObject * self = (StructParamObject * )myself ;
423- Py_XDECREF (self -> keep );
434+ PyTypeObject * tp = Py_TYPE (self );
435+ PyObject_GC_UnTrack (myself );
436+ (void )StructParam_clear (self );
424437 PyMem_Free (self -> ptr );
425- Py_TYPE (self )-> tp_free (myself );
438+ tp -> tp_free (myself );
439+ Py_DECREF (tp );
426440}
427441
442+ static PyType_Slot structparam_slots [] = {
443+ {Py_tp_traverse , StructParam_traverse },
444+ {Py_tp_clear , StructParam_clear },
445+ {Py_tp_dealloc , StructParam_dealloc },
446+ {0 , NULL },
447+ };
428448
429- static PyTypeObject StructParam_Type = {
430- PyVarObject_HEAD_INIT ( NULL , 0 )
431- .tp_name = "_ctypes.StructParam_Type" ,
432- .tp_basicsize = sizeof ( StructParamObject ),
433- . tp_dealloc = StructParam_dealloc ,
434- .tp_flags = Py_TPFLAGS_DEFAULT ,
449+ static PyType_Spec structparam_spec = {
450+ . name = "_ctypes.StructParam_Type" ,
451+ .basicsize = sizeof ( StructParamObject ) ,
452+ .flags = ( Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE |
453+ Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_DISALLOW_INSTANTIATION ) ,
454+ .slots = structparam_slots ,
435455};
436456
437457
@@ -460,7 +480,9 @@ StructUnionType_paramfunc(CDataObject *self)
460480 /* Create a Python object which calls PyMem_Free(ptr) in
461481 its deallocator. The object will be destroyed
462482 at _ctypes_callproc() cleanup. */
463- obj = (& StructParam_Type )-> tp_alloc (& StructParam_Type , 0 );
483+ ctypes_state * st = GLOBAL_STATE ();
484+ PyTypeObject * tp = st -> StructParam_Type ;
485+ obj = tp -> tp_alloc (tp , 0 );
464486 if (obj == NULL ) {
465487 PyMem_Free (ptr );
466488 return NULL ;
@@ -800,7 +822,8 @@ CDataType_from_param(PyObject *type, PyObject *value)
800822 if (res ) {
801823 return Py_NewRef (value );
802824 }
803- if (PyCArg_CheckExact (value )) {
825+ ctypes_state * st = GLOBAL_STATE ();
826+ if (PyCArg_CheckExact (st , value )) {
804827 PyCArgObject * p = (PyCArgObject * )value ;
805828 PyObject * ob = p -> obj ;
806829 const char * ob_name ;
@@ -1683,7 +1706,8 @@ c_wchar_p_from_param(PyObject *type, PyObject *value)
16831706 return Py_NewRef (value );
16841707 }
16851708 }
1686- if (PyCArg_CheckExact (value )) {
1709+ ctypes_state * st = GLOBAL_STATE ();
1710+ if (PyCArg_CheckExact (st , value )) {
16871711 /* byref(c_char(...)) */
16881712 PyCArgObject * a = (PyCArgObject * )value ;
16891713 StgDictObject * dict = PyObject_stgdict (a -> obj );
@@ -1746,7 +1770,8 @@ c_char_p_from_param(PyObject *type, PyObject *value)
17461770 return Py_NewRef (value );
17471771 }
17481772 }
1749- if (PyCArg_CheckExact (value )) {
1773+ ctypes_state * st = GLOBAL_STATE ();
1774+ if (PyCArg_CheckExact (st , value )) {
17501775 /* byref(c_char(...)) */
17511776 PyCArgObject * a = (PyCArgObject * )value ;
17521777 StgDictObject * dict = PyObject_stgdict (a -> obj );
@@ -1847,7 +1872,8 @@ c_void_p_from_param(PyObject *type, PyObject *value)
18471872 return Py_NewRef (value );
18481873 }
18491874/* byref(...) */
1850- if (PyCArg_CheckExact (value )) {
1875+ ctypes_state * st = GLOBAL_STATE ();
1876+ if (PyCArg_CheckExact (st , value )) {
18511877 /* byref(c_xxx()) */
18521878 PyCArgObject * a = (PyCArgObject * )value ;
18531879 if (a -> tag == 'P' ) {
@@ -5635,12 +5661,22 @@ _ctypes_add_types(PyObject *mod)
56355661 } \
56365662 } while (0)
56375663
5664+ #define CREATE_TYPE (MOD , TP , SPEC ) do { \
5665+ PyObject *type = PyType_FromMetaclass(NULL, MOD, SPEC, NULL); \
5666+ if (type == NULL) { \
5667+ return -1; \
5668+ } \
5669+ TP = (PyTypeObject *)type; \
5670+ } while (0)
5671+
5672+ ctypes_state * st = GLOBAL_STATE ();
5673+
56385674 /* Note:
56395675 ob_type is the metatype (the 'type'), defaults to PyType_Type,
56405676 tp_base is the base type, defaults to 'object' aka PyBaseObject_Type.
56415677 */
5642- TYPE_READY ( & PyCArg_Type );
5643- TYPE_READY ( & PyCThunk_Type );
5678+ CREATE_TYPE ( mod , st -> PyCArg_Type , & carg_spec );
5679+ CREATE_TYPE ( mod , st -> PyCThunk_Type , & cthunk_spec );
56445680 TYPE_READY (& PyCData_Type );
56455681 /* StgDict is derived from PyDict_Type */
56465682 TYPE_READY_BASE (& PyCStgDict_Type , & PyDict_Type );
@@ -5673,17 +5709,15 @@ _ctypes_add_types(PyObject *mod)
56735709 * Simple classes
56745710 */
56755711
5676- /* PyCField_Type is derived from PyBaseObject_Type */
5677- TYPE_READY (& PyCField_Type );
5712+ CREATE_TYPE (mod , st -> PyCField_Type , & cfield_spec );
56785713
56795714 /*************************************************
56805715 *
56815716 * Other stuff
56825717 */
56835718
5684- DictRemover_Type .tp_new = PyType_GenericNew ;
5685- TYPE_READY (& DictRemover_Type );
5686- TYPE_READY (& StructParam_Type );
5719+ CREATE_TYPE (mod , st -> DictRemover_Type , & dictremover_spec );
5720+ CREATE_TYPE (mod , st -> StructParam_Type , & structparam_spec );
56875721
56885722#ifdef MS_WIN32
56895723 TYPE_READY_BASE (& PyComError_Type , (PyTypeObject * )PyExc_Exception );
@@ -5692,6 +5726,7 @@ _ctypes_add_types(PyObject *mod)
56925726#undef TYPE_READY
56935727#undef TYPE_READY_BASE
56945728#undef MOD_ADD_TYPE
5729+ #undef CREATE_TYPE
56955730 return 0 ;
56965731}
56975732
0 commit comments