Skip to content

Commit 4f524da

Browse files
gh-103092: Port _ctypes.COMError to heap type (#104020)
1 parent ef0df52 commit 4f524da

File tree

3 files changed

+47
-60
lines changed

3 files changed

+47
-60
lines changed

Modules/_ctypes/_ctypes.c

+42-55
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,6 @@ static PyTypeObject Simple_Type;
139139
strong reference to _ctypes._unpickle() function */
140140
static PyObject *_unpickle;
141141

142-
#ifdef MS_WIN32
143-
PyObject *ComError; // Borrowed reference to: &PyComError_Type
144-
#endif
145-
146142

147143
/****************************************************************/
148144

@@ -5480,46 +5476,38 @@ comerror_init(PyObject *self, PyObject *args, PyObject *kwds)
54805476
return 0;
54815477
}
54825478

5483-
static PyTypeObject PyComError_Type = {
5484-
PyVarObject_HEAD_INIT(NULL, 0)
5485-
"_ctypes.COMError", /* tp_name */
5486-
sizeof(PyBaseExceptionObject), /* tp_basicsize */
5487-
0, /* tp_itemsize */
5488-
0, /* tp_dealloc */
5489-
0, /* tp_vectorcall_offset */
5490-
0, /* tp_getattr */
5491-
0, /* tp_setattr */
5492-
0, /* tp_as_async */
5493-
0, /* tp_repr */
5494-
0, /* tp_as_number */
5495-
0, /* tp_as_sequence */
5496-
0, /* tp_as_mapping */
5497-
0, /* tp_hash */
5498-
0, /* tp_call */
5499-
0, /* tp_str */
5500-
0, /* tp_getattro */
5501-
0, /* tp_setattro */
5502-
0, /* tp_as_buffer */
5503-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
5504-
PyDoc_STR(comerror_doc), /* tp_doc */
5505-
0, /* tp_traverse */
5506-
0, /* tp_clear */
5507-
0, /* tp_richcompare */
5508-
0, /* tp_weaklistoffset */
5509-
0, /* tp_iter */
5510-
0, /* tp_iternext */
5511-
0, /* tp_methods */
5512-
0, /* tp_members */
5513-
0, /* tp_getset */
5514-
0, /* tp_base */
5515-
0, /* tp_dict */
5516-
0, /* tp_descr_get */
5517-
0, /* tp_descr_set */
5518-
0, /* tp_dictoffset */
5519-
(initproc)comerror_init, /* tp_init */
5520-
0, /* tp_alloc */
5521-
0, /* tp_new */
5479+
static int
5480+
comerror_traverse(PyObject *self, visitproc visit, void *arg)
5481+
{
5482+
Py_VISIT(Py_TYPE(self));
5483+
return 0;
5484+
}
5485+
5486+
static void
5487+
comerror_dealloc(PyObject *self)
5488+
{
5489+
PyTypeObject *tp = Py_TYPE(self);
5490+
PyObject_GC_UnTrack(self);
5491+
tp->tp_free(self);
5492+
Py_DECREF(tp);
5493+
}
5494+
5495+
static PyType_Slot comerror_slots[] = {
5496+
{Py_tp_doc, (void *)PyDoc_STR(comerror_doc)},
5497+
{Py_tp_init, comerror_init},
5498+
{Py_tp_traverse, comerror_traverse},
5499+
{Py_tp_dealloc, comerror_dealloc},
5500+
{0, NULL},
55225501
};
5502+
5503+
static PyType_Spec comerror_spec = {
5504+
.name = "_ctypes.COMError",
5505+
.basicsize = sizeof(PyBaseExceptionObject),
5506+
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
5507+
Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
5508+
.slots = comerror_slots,
5509+
};
5510+
55235511
#endif // MS_WIN32
55245512

55255513
static PyObject *
@@ -5661,8 +5649,9 @@ _ctypes_add_types(PyObject *mod)
56615649
} \
56625650
} while (0)
56635651

5664-
#define CREATE_TYPE(MOD, TP, SPEC) do { \
5665-
PyObject *type = PyType_FromMetaclass(NULL, MOD, SPEC, NULL); \
5652+
#define CREATE_TYPE(MOD, TP, SPEC, BASE) do { \
5653+
PyObject *type = PyType_FromMetaclass(NULL, MOD, SPEC, \
5654+
(PyObject *)BASE); \
56665655
if (type == NULL) { \
56675656
return -1; \
56685657
} \
@@ -5675,8 +5664,8 @@ _ctypes_add_types(PyObject *mod)
56755664
ob_type is the metatype (the 'type'), defaults to PyType_Type,
56765665
tp_base is the base type, defaults to 'object' aka PyBaseObject_Type.
56775666
*/
5678-
CREATE_TYPE(mod, st->PyCArg_Type, &carg_spec);
5679-
CREATE_TYPE(mod, st->PyCThunk_Type, &cthunk_spec);
5667+
CREATE_TYPE(mod, st->PyCArg_Type, &carg_spec, NULL);
5668+
CREATE_TYPE(mod, st->PyCThunk_Type, &cthunk_spec, NULL);
56805669
TYPE_READY(&PyCData_Type);
56815670
/* StgDict is derived from PyDict_Type */
56825671
TYPE_READY_BASE(&PyCStgDict_Type, &PyDict_Type);
@@ -5709,18 +5698,18 @@ _ctypes_add_types(PyObject *mod)
57095698
* Simple classes
57105699
*/
57115700

5712-
CREATE_TYPE(mod, st->PyCField_Type, &cfield_spec);
5701+
CREATE_TYPE(mod, st->PyCField_Type, &cfield_spec, NULL);
57135702

57145703
/*************************************************
57155704
*
57165705
* Other stuff
57175706
*/
57185707

5719-
CREATE_TYPE(mod, st->DictRemover_Type, &dictremover_spec);
5720-
CREATE_TYPE(mod, st->StructParam_Type, &structparam_spec);
5708+
CREATE_TYPE(mod, st->DictRemover_Type, &dictremover_spec, NULL);
5709+
CREATE_TYPE(mod, st->StructParam_Type, &structparam_spec, NULL);
57215710

57225711
#ifdef MS_WIN32
5723-
TYPE_READY_BASE(&PyComError_Type, (PyTypeObject*)PyExc_Exception);
5712+
CREATE_TYPE(mod, st->PyComError_Type, &comerror_spec, PyExc_Exception);
57245713
#endif
57255714

57265715
#undef TYPE_READY
@@ -5750,7 +5739,8 @@ _ctypes_add_objects(PyObject *mod)
57505739
MOD_ADD("_pointer_type_cache", Py_NewRef(_ctypes_ptrtype_cache));
57515740

57525741
#ifdef MS_WIN32
5753-
MOD_ADD("COMError", Py_NewRef(ComError));
5742+
ctypes_state *st = GLOBAL_STATE();
5743+
MOD_ADD("COMError", Py_NewRef(st->PyComError_Type));
57545744
MOD_ADD("FUNCFLAG_HRESULT", PyLong_FromLong(FUNCFLAG_HRESULT));
57555745
MOD_ADD("FUNCFLAG_STDCALL", PyLong_FromLong(FUNCFLAG_STDCALL));
57565746
#endif
@@ -5807,9 +5797,6 @@ _ctypes_mod_exec(PyObject *mod)
58075797
if (_ctypes_add_types(mod) < 0) {
58085798
return -1;
58095799
}
5810-
#ifdef MS_WIN32
5811-
ComError = (PyObject*)&PyComError_Type;
5812-
#endif
58135800

58145801
if (_ctypes_add_objects(mod) < 0) {
58155802
return -1;

Modules/_ctypes/callproc.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,8 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk)
11151115
descr, source, helpfile, helpcontext,
11161116
progid);
11171117
if (obj) {
1118-
PyErr_SetObject(ComError, obj);
1118+
ctypes_state *st = GLOBAL_STATE();
1119+
PyErr_SetObject((PyObject *)st->PyComError_Type, obj);
11191120
Py_DECREF(obj);
11201121
}
11211122
LocalFree(text);

Modules/_ctypes/ctypes.h

+3-4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ typedef struct {
3737
PyTypeObject *PyCArg_Type;
3838
PyTypeObject *PyCField_Type;
3939
PyTypeObject *PyCThunk_Type;
40+
#ifdef MS_WIN32
41+
PyTypeObject *PyComError_Type;
42+
#endif
4043
PyTypeObject *StructParam_Type;
4144
} ctypes_state;
4245

@@ -392,10 +395,6 @@ extern int _ctypes_simple_instance(PyObject *obj);
392395
extern PyObject *_ctypes_ptrtype_cache;
393396
PyObject *_ctypes_get_errobj(int **pspace);
394397

395-
#ifdef MS_WIN32
396-
extern PyObject *ComError;
397-
#endif
398-
399398
#ifdef USING_MALLOC_CLOSURE_DOT_C
400399
void Py_ffi_closure_free(void *p);
401400
void *Py_ffi_closure_alloc(size_t size, void** codeloc);

0 commit comments

Comments
 (0)