@@ -126,6 +126,8 @@ bytes(cdata)
126
126
127
127
#include "pycore_long.h" // _PyLong_GetZero()
128
128
129
+ ctypes_state global_state ;
130
+
129
131
PyObject * PyExc_ArgError = NULL ;
130
132
131
133
/* This dict maps ctypes types to POINTER types */
@@ -150,13 +152,32 @@ typedef struct {
150
152
PyObject * dict ;
151
153
} DictRemoverObject ;
152
154
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
+
153
172
static void
154
173
_DictRemover_dealloc (PyObject * myself )
155
174
{
175
+ PyTypeObject * tp = Py_TYPE (myself );
156
176
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 );
160
181
}
161
182
162
183
static PyObject *
@@ -173,47 +194,23 @@ _DictRemover_call(PyObject *myself, PyObject *args, PyObject *kw)
173
194
Py_RETURN_NONE ;
174
195
}
175
196
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 ,
217
214
};
218
215
219
216
int
@@ -224,7 +221,8 @@ PyDict_SetItemProxy(PyObject *dict, PyObject *key, PyObject *item)
224
221
PyObject * proxy ;
225
222
int result ;
226
223
227
- obj = _PyObject_CallNoArgs ((PyObject * )& DictRemover_Type );
224
+ ctypes_state * st = GLOBAL_STATE ();
225
+ obj = _PyObject_CallNoArgs ((PyObject * )st -> DictRemover_Type );
228
226
if (obj == NULL )
229
227
return -1 ;
230
228
@@ -415,23 +413,45 @@ typedef struct {
415
413
PyObject * keep ; // If set, a reference to the original CDataObject.
416
414
} StructParamObject ;
417
415
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
+ }
418
429
419
430
static void
420
431
StructParam_dealloc (PyObject * myself )
421
432
{
422
433
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 );
424
437
PyMem_Free (self -> ptr );
425
- Py_TYPE (self )-> tp_free (myself );
438
+ tp -> tp_free (myself );
439
+ Py_DECREF (tp );
426
440
}
427
441
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
+ };
428
448
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 ,
435
455
};
436
456
437
457
@@ -460,7 +480,9 @@ StructUnionType_paramfunc(CDataObject *self)
460
480
/* Create a Python object which calls PyMem_Free(ptr) in
461
481
its deallocator. The object will be destroyed
462
482
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 );
464
486
if (obj == NULL ) {
465
487
PyMem_Free (ptr );
466
488
return NULL ;
@@ -800,7 +822,8 @@ CDataType_from_param(PyObject *type, PyObject *value)
800
822
if (res ) {
801
823
return Py_NewRef (value );
802
824
}
803
- if (PyCArg_CheckExact (value )) {
825
+ ctypes_state * st = GLOBAL_STATE ();
826
+ if (PyCArg_CheckExact (st , value )) {
804
827
PyCArgObject * p = (PyCArgObject * )value ;
805
828
PyObject * ob = p -> obj ;
806
829
const char * ob_name ;
@@ -1683,7 +1706,8 @@ c_wchar_p_from_param(PyObject *type, PyObject *value)
1683
1706
return Py_NewRef (value );
1684
1707
}
1685
1708
}
1686
- if (PyCArg_CheckExact (value )) {
1709
+ ctypes_state * st = GLOBAL_STATE ();
1710
+ if (PyCArg_CheckExact (st , value )) {
1687
1711
/* byref(c_char(...)) */
1688
1712
PyCArgObject * a = (PyCArgObject * )value ;
1689
1713
StgDictObject * dict = PyObject_stgdict (a -> obj );
@@ -1746,7 +1770,8 @@ c_char_p_from_param(PyObject *type, PyObject *value)
1746
1770
return Py_NewRef (value );
1747
1771
}
1748
1772
}
1749
- if (PyCArg_CheckExact (value )) {
1773
+ ctypes_state * st = GLOBAL_STATE ();
1774
+ if (PyCArg_CheckExact (st , value )) {
1750
1775
/* byref(c_char(...)) */
1751
1776
PyCArgObject * a = (PyCArgObject * )value ;
1752
1777
StgDictObject * dict = PyObject_stgdict (a -> obj );
@@ -1847,7 +1872,8 @@ c_void_p_from_param(PyObject *type, PyObject *value)
1847
1872
return Py_NewRef (value );
1848
1873
}
1849
1874
/* byref(...) */
1850
- if (PyCArg_CheckExact (value )) {
1875
+ ctypes_state * st = GLOBAL_STATE ();
1876
+ if (PyCArg_CheckExact (st , value )) {
1851
1877
/* byref(c_xxx()) */
1852
1878
PyCArgObject * a = (PyCArgObject * )value ;
1853
1879
if (a -> tag == 'P' ) {
@@ -5635,12 +5661,22 @@ _ctypes_add_types(PyObject *mod)
5635
5661
} \
5636
5662
} while (0)
5637
5663
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
+
5638
5674
/* Note:
5639
5675
ob_type is the metatype (the 'type'), defaults to PyType_Type,
5640
5676
tp_base is the base type, defaults to 'object' aka PyBaseObject_Type.
5641
5677
*/
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 );
5644
5680
TYPE_READY (& PyCData_Type );
5645
5681
/* StgDict is derived from PyDict_Type */
5646
5682
TYPE_READY_BASE (& PyCStgDict_Type , & PyDict_Type );
@@ -5673,17 +5709,15 @@ _ctypes_add_types(PyObject *mod)
5673
5709
* Simple classes
5674
5710
*/
5675
5711
5676
- /* PyCField_Type is derived from PyBaseObject_Type */
5677
- TYPE_READY (& PyCField_Type );
5712
+ CREATE_TYPE (mod , st -> PyCField_Type , & cfield_spec );
5678
5713
5679
5714
/*************************************************
5680
5715
*
5681
5716
* Other stuff
5682
5717
*/
5683
5718
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 );
5687
5721
5688
5722
#ifdef MS_WIN32
5689
5723
TYPE_READY_BASE (& PyComError_Type , (PyTypeObject * )PyExc_Exception );
@@ -5692,6 +5726,7 @@ _ctypes_add_types(PyObject *mod)
5692
5726
#undef TYPE_READY
5693
5727
#undef TYPE_READY_BASE
5694
5728
#undef MOD_ADD_TYPE
5729
+ #undef CREATE_TYPE
5695
5730
return 0 ;
5696
5731
}
5697
5732
0 commit comments