From dd44ab994b7262f0704d64996e0a1bc37b233407 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Mon, 1 Apr 2024 22:28:14 +0900 Subject: [PATCH] gh-117142: ctypes: Unify meta tp slot functions (GH-117143) Integrates the following ctypes meta tp slot functions: * `CDataType_traverse()` into `CType_Type_traverse()`. * `CDataType_clear()` into `CType_Type_clear()`. * `CDataType_dealloc()` into `CType_Type_dealloc()`. * `CDataType_repeat()` into `CType_Type_repeat()`. --- Modules/_ctypes/_ctypes.c | 109 +++++++++++++------------------------- Modules/_ctypes/ctypes.h | 8 +++ Modules/_ctypes/stgdict.c | 2 + 3 files changed, 46 insertions(+), 73 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 6bd1893480027c..631f82879311bf 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -441,12 +441,27 @@ static PyType_Spec structparam_spec = { static int CType_Type_traverse(PyObject *self, visitproc visit, void *arg) { + ctypes_state *st = GLOBAL_STATE(); + if (st && st->PyCType_Type) { + StgInfo *info; + if (PyStgInfo_FromType(st, self, &info) < 0) { + PyErr_WriteUnraisable(self); + } + if (info) { + Py_VISIT(info->proto); + Py_VISIT(info->argtypes); + Py_VISIT(info->converters); + Py_VISIT(info->restype); + Py_VISIT(info->checker); + Py_VISIT(info->module); + } + } Py_VISIT(Py_TYPE(self)); - return 0; + return PyType_Type.tp_traverse(self, visit, arg); } -static void -_ctype_clear_stginfo(StgInfo *info) +void +ctype_clear_stginfo(StgInfo *info) { assert(info); Py_CLEAR(info->proto); @@ -454,6 +469,7 @@ _ctype_clear_stginfo(StgInfo *info) Py_CLEAR(info->converters); Py_CLEAR(info->restype); Py_CLEAR(info->checker); + Py_CLEAR(info->module); } static int @@ -463,13 +479,13 @@ CType_Type_clear(PyObject *self) if (st && st->PyCType_Type) { StgInfo *info; if (PyStgInfo_FromType(st, self, &info) < 0) { - return -1; + PyErr_WriteUnraisable(self); } if (info) { - _ctype_clear_stginfo(info); + ctype_clear_stginfo(info); } } - return 0; + return PyType_Type.tp_clear(self); } static void @@ -489,7 +505,7 @@ CType_Type_dealloc(PyObject *self) info->format = NULL; PyMem_Free(info->shape); info->shape = NULL; - _ctype_clear_stginfo(info); + ctype_clear_stginfo(info); } } @@ -522,6 +538,10 @@ CType_Type_sizeof(PyObject *self) return PyLong_FromSsize_t(size); } +static PyObject * +CType_Type_repeat(PyObject *self, Py_ssize_t length); + + static PyMethodDef ctype_methods[] = { {"__sizeof__", _PyCFunction_CAST(CType_Type_sizeof), METH_NOARGS, PyDoc_STR("Return memory consumption of the type object.")}, @@ -533,6 +553,8 @@ static PyType_Slot ctype_type_slots[] = { {Py_tp_clear, CType_Type_clear}, {Py_tp_dealloc, CType_Type_dealloc}, {Py_tp_methods, ctype_methods}, + // Sequence protocol. + {Py_sq_repeat, CType_Type_repeat}, {0, NULL}, }; @@ -978,7 +1000,7 @@ static PyMethodDef CDataType_methods[] = { }; static PyObject * -CDataType_repeat(PyObject *self, Py_ssize_t length) +CType_Type_repeat(PyObject *self, Py_ssize_t length) { if (length < 0) return PyErr_Format(PyExc_ValueError, @@ -988,35 +1010,6 @@ CDataType_repeat(PyObject *self, Py_ssize_t length) return PyCArrayType_from_ctype(st, self, length); } -static int -CDataType_clear(PyTypeObject *self) -{ - ctypes_state *st = GLOBAL_STATE(); - StgInfo *info; - if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) { - return -1; - } - if (info) { - Py_CLEAR(info->proto); - } - return PyType_Type.tp_clear((PyObject *)self); -} - -static int -CDataType_traverse(PyTypeObject *self, visitproc visit, void *arg) -{ - ctypes_state *st = GLOBAL_STATE(); - StgInfo *info; - if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) { - return -1; - } - if (info) { - Py_VISIT(info->proto); - } - Py_VISIT(Py_TYPE(self)); - return PyType_Type.tp_traverse((PyObject *)self, visit, arg); -} - static int PyCStructType_setattro(PyObject *self, PyObject *key, PyObject *value) { @@ -1047,19 +1040,14 @@ UnionType_setattro(PyObject *self, PyObject *key, PyObject *value) static PyType_Slot pycstruct_type_slots[] = { {Py_tp_setattro, PyCStructType_setattro}, {Py_tp_doc, PyDoc_STR("metatype for the CData Objects")}, - {Py_tp_traverse, CDataType_traverse}, - {Py_tp_clear, CDataType_clear}, {Py_tp_methods, CDataType_methods}, {Py_tp_init, PyCStructType_init}, - - // Sequence protocol. - {Py_sq_repeat, CDataType_repeat}, {0, NULL}, }; static PyType_Spec pycstruct_type_spec = { .name = "_ctypes.PyCStructType", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = pycstruct_type_slots, }; @@ -1067,19 +1055,14 @@ static PyType_Spec pycstruct_type_spec = { static PyType_Slot union_type_slots[] = { {Py_tp_setattro, UnionType_setattro}, {Py_tp_doc, PyDoc_STR("metatype for the Union Objects")}, - {Py_tp_traverse, CDataType_traverse}, - {Py_tp_clear, CDataType_clear}, {Py_tp_methods, CDataType_methods}, {Py_tp_init, UnionType_init}, - - // Sequence protocol. - {Py_sq_repeat, CDataType_repeat}, {0, NULL}, }; static PyType_Spec union_type_spec = { .name = "_ctypes.UnionType", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = union_type_slots, }; @@ -1305,19 +1288,14 @@ static PyMethodDef PyCPointerType_methods[] = { static PyType_Slot pycpointer_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for the Pointer Objects")}, - {Py_tp_traverse, CDataType_traverse}, - {Py_tp_clear, CDataType_clear}, {Py_tp_methods, PyCPointerType_methods}, {Py_tp_init, PyCPointerType_init}, - - // Sequence protocol. - {Py_sq_repeat, CDataType_repeat}, {0, NULL}, }; static PyType_Spec pycpointer_type_spec = { .name = "_ctypes.PyCPointerType", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = pycpointer_type_slots, }; @@ -1640,19 +1618,14 @@ PyCArrayType_init(PyObject *self, PyObject *args, PyObject *kwds) static PyType_Slot pycarray_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for the Array Objects")}, - {Py_tp_traverse, CDataType_traverse}, {Py_tp_methods, CDataType_methods}, {Py_tp_init, PyCArrayType_init}, - {Py_tp_clear, CDataType_clear}, - - // Sequence protocol. - {Py_sq_repeat, CDataType_repeat}, {0, NULL}, }; static PyType_Spec pycarray_type_spec = { .name = "_ctypes.PyCArrayType", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = pycarray_type_slots, }; @@ -2315,17 +2288,12 @@ static PyType_Slot pycsimple_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for the PyCSimpleType Objects")}, {Py_tp_methods, PyCSimpleType_methods}, {Py_tp_init, PyCSimpleType_init}, - {Py_tp_traverse, CDataType_traverse}, - {Py_tp_clear, CDataType_clear}, - - // Sequence protocol. - {Py_sq_repeat, CDataType_repeat}, {0, NULL}, }; static PyType_Spec pycsimple_type_spec = { .name = "_ctypes.PyCSimpleType", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = pycsimple_type_slots, }; @@ -2570,19 +2538,14 @@ PyCFuncPtrType_init(PyObject *self, PyObject *args, PyObject *kwds) static PyType_Slot pycfuncptr_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for C function pointers")}, - {Py_tp_traverse, CDataType_traverse}, - {Py_tp_clear, CDataType_clear}, {Py_tp_methods, CDataType_methods}, {Py_tp_init, PyCFuncPtrType_init}, - - // Sequence protocol. - {Py_sq_repeat, CDataType_repeat}, {0, NULL}, }; static PyType_Spec pycfuncptr_type_spec = { .name = "_ctypes.PyCFuncPtrType", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = pycfuncptr_type_slots, }; diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 3422310045bcc9..31b89dca244e8e 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -302,6 +302,7 @@ typedef struct { PyObject *converters; /* tuple([t.from_param for t in argtypes]) */ PyObject *restype; /* CDataObject or NULL */ PyObject *checker; + PyObject *module; int flags; /* calling convention and such */ /* pep3118 fields, pointers need PyMem_Free */ @@ -313,6 +314,7 @@ typedef struct { } StgInfo; extern int PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info); +extern void ctype_clear_stginfo(StgInfo *info); typedef int(* PPROC)(void); @@ -481,6 +483,12 @@ PyStgInfo_Init(ctypes_state *state, PyTypeObject *type) type->tp_name); return NULL; } + PyObject *module = PyType_GetModule(state->PyCType_Type); + if (!module) { + return NULL; + } + info->module = Py_NewRef(module); + info->initialized = 1; return info; } diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 53e7dc39614d21..7b09bae0dd2a57 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -25,6 +25,7 @@ PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info) { Py_ssize_t size; + ctype_clear_stginfo(dst_info); PyMem_Free(dst_info->ffi_type_pointer.elements); PyMem_Free(dst_info->format); dst_info->format = NULL; @@ -39,6 +40,7 @@ PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info) Py_XINCREF(dst_info->converters); Py_XINCREF(dst_info->restype); Py_XINCREF(dst_info->checker); + Py_XINCREF(dst_info->module); if (src_info->format) { dst_info->format = PyMem_Malloc(strlen(src_info->format) + 1);