]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-117142: ctypes: Unify meta tp slot functions (GH-117143)
authorneonene <53406459+neonene@users.noreply.github.com>
Mon, 1 Apr 2024 13:28:14 +0000 (22:28 +0900)
committerGitHub <noreply@github.com>
Mon, 1 Apr 2024 13:28:14 +0000 (15:28 +0200)
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
Modules/_ctypes/ctypes.h
Modules/_ctypes/stgdict.c

index 6bd1893480027c6b2e2c0ca3b02859298907ba9d..631f82879311bf9cb366b2e9c8f58a4aeb2b7a4d 100644 (file)
@@ -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 @@ error:
 
 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,
 };
index 3422310045bcc9415e07a3e19a3fee6b6603e3b4..31b89dca244e8ec2bc927e629cf1f84dcdf9ff6e 100644 (file)
@@ -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;
 }
index 53e7dc39614d210a50d8769592d540c1f92d6cc9..7b09bae0dd2a57271e3a5e06f5bb3d74b55d6383 100644 (file)
@@ -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);