diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 94245ae41afffc..481361ea437f40 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -128,19 +128,8 @@ bytes(cdata) #include "pycore_long.h" // _PyLong_GetZero() -static PyTypeObject Union_Type; -static PyTypeObject Struct_Type; -static PyTypeObject Simple_Type; - ctypes_state global_state = { .PyCStgDict_Type = &PyCStgDict_Type, - .PyCData_Type = &PyCData_Type, - .Struct_Type = &Struct_Type, - .Union_Type = &Union_Type, - .PyCArray_Type = &PyCArray_Type, - .Simple_Type = &Simple_Type, - .PyCPointer_Type = &PyCPointer_Type, - .PyCFuncPtr_Type = &PyCFuncPtr_Type, }; PyObject *PyExc_ArgError = NULL; @@ -462,8 +451,8 @@ static PyType_Spec structparam_spec = { /* PyCStructType_Type - a meta type/class. Creating a new class using this one as - __metaclass__ will call the constructor StructUnionType_new. It replaces the - tp_dict member with a new instance of StgDict, and initializes the C + __metaclass__ will call the constructor StructUnionType_new/init. It replaces + the tp_dict member with a new instance of StgDict, and initializes the C accessible fields somehow. */ @@ -517,8 +506,8 @@ StructUnionType_paramfunc(CDataObject *self) return parg; } -static PyObject * -StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isStruct) +static int +StructUnionType_init(PyObject *self, PyObject *args, PyObject *kwds, int isStruct) { PyTypeObject *result; PyObject *fields; @@ -526,25 +515,21 @@ StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isSt /* create the new instance (which is a class, since we are a metatype!) */ - result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds); - if (!result) - return NULL; + result = (PyTypeObject *)self; // by PyType_Type.tp_new() /* keep this for bw compatibility */ int r = PyDict_Contains(result->tp_dict, &_Py_ID(_abstract_)); if (r > 0) { - return (PyObject *)result; + return 0; } if (r < 0) { - Py_DECREF(result); - return NULL; + return -1; } ctypes_state *st = GLOBAL_STATE(); dict = (StgDictObject *)_PyObject_CallNoArgs((PyObject *)st->PyCStgDict_Type); if (!dict) { - Py_DECREF(result); - return NULL; + return -1; } if (!isStruct) { dict->flags |= TYPEFLAG_HASUNION; @@ -552,59 +537,54 @@ StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isSt /* replace the class dict by our updated stgdict, which holds info about storage requirements of the instances */ if (-1 == PyDict_Update((PyObject *)dict, result->tp_dict)) { - Py_DECREF(result); Py_DECREF((PyObject *)dict); - return NULL; + return -1; } Py_SETREF(result->tp_dict, (PyObject *)dict); dict->format = _ctypes_alloc_format_string(NULL, "B"); if (dict->format == NULL) { - Py_DECREF(result); - return NULL; + return -1; } dict->paramfunc = StructUnionType_paramfunc; if (PyDict_GetItemRef((PyObject *)dict, &_Py_ID(_fields_), &fields) < 0) { - Py_DECREF(result); - return NULL; + return -1; } if (fields) { if (PyObject_SetAttr((PyObject *)result, &_Py_ID(_fields_), fields) < 0) { - Py_DECREF(result); Py_DECREF(fields); - return NULL; + return -1; } Py_DECREF(fields); - return (PyObject *)result; + return 0; } else { StgDictObject *basedict = PyType_stgdict((PyObject *)result->tp_base); if (basedict == NULL) { - return (PyObject *)result; + return 0; } /* copy base dict */ if (-1 == PyCStgDict_clone(dict, basedict)) { - Py_DECREF(result); - return NULL; + return -1; } dict->flags &= ~DICTFLAG_FINAL; /* clear the 'final' flag in the subclass dict */ basedict->flags |= DICTFLAG_FINAL; /* set the 'final' flag in the baseclass dict */ - return (PyObject *)result; + return 0; } } -static PyObject * -PyCStructType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int +PyCStructType_init(PyObject *self, PyObject *args, PyObject *kwds) { - return StructUnionType_new(type, args, kwds, 1); + return StructUnionType_init(self, args, kwds, 1); } -static PyObject * -UnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int +UnionType_init(PyObject *self, PyObject *args, PyObject *kwds) { - return StructUnionType_new(type, args, kwds, 0); + return StructUnionType_init(self, args, kwds, 0); } PyDoc_STRVAR(from_address_doc, @@ -943,7 +923,7 @@ static PyType_Slot pycstruct_type_slots[] = { {Py_tp_traverse, CDataType_traverse}, {Py_tp_clear, CDataType_clear}, {Py_tp_methods, CDataType_methods}, - {Py_tp_new, PyCStructType_new}, + {Py_tp_init, PyCStructType_init}, // Sequence protocol. {Py_sq_repeat, CDataType_repeat}, @@ -963,7 +943,7 @@ static PyType_Slot union_type_slots[] = { {Py_tp_traverse, CDataType_traverse}, {Py_tp_clear, CDataType_clear}, {Py_tp_methods, CDataType_methods}, - {Py_tp_new, UnionType_new}, + {Py_tp_init, UnionType_init}, // Sequence protocol. {Py_sq_repeat, CDataType_repeat}, @@ -1027,8 +1007,8 @@ PyCPointerType_paramfunc(CDataObject *self) return parg; } -static PyObject * -PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int +PyCPointerType_init(PyObject *self, PyObject *args, PyObject *kwds) { PyTypeObject *result; StgDictObject *stgdict; @@ -1038,7 +1018,7 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) typedict = PyTuple_GetItem(args, 2); if (!typedict) { - return NULL; + return -1; } /* stgdict items size, align, length contain info about pointers itself, @@ -1048,7 +1028,7 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) stgdict = (StgDictObject *)_PyObject_CallNoArgs( (PyObject *)st->PyCStgDict_Type); if (!stgdict) { - return NULL; + return -1; } stgdict->size = sizeof(void *); stgdict->align = _ctypes_get_fielddesc("P")->pffi_type->alignment; @@ -1059,7 +1039,7 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (PyDict_GetItemRef(typedict, &_Py_ID(_type_), &proto) < 0) { Py_DECREF((PyObject *)stgdict); - return NULL; + return -1; } if (proto) { StgDictObject *itemdict; @@ -1067,7 +1047,7 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (-1 == PyCPointerType_SetProto(stgdict, proto)) { Py_DECREF(proto); Py_DECREF((PyObject *)stgdict); - return NULL; + return -1; } itemdict = PyType_stgdict(proto); /* PyCPointerType_SetProto has verified proto has a stgdict. */ @@ -1088,27 +1068,22 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_DECREF(proto); if (stgdict->format == NULL) { Py_DECREF((PyObject *)stgdict); - return NULL; + return -1; } } /* create the new instance (which is a class, since we are a metatype!) */ - result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds); - if (result == NULL) { - Py_DECREF((PyObject *)stgdict); - return NULL; - } + result = (PyTypeObject *)self; // by PyType_Type.tp_new() /* replace the class dict by our updated spam dict */ if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) { - Py_DECREF(result); Py_DECREF((PyObject *)stgdict); - return NULL; + return -1; } Py_SETREF(result->tp_dict, (PyObject *)stgdict); - return (PyObject *)result; + return 0; } @@ -1199,7 +1174,7 @@ static PyType_Slot pycpointer_type_slots[] = { {Py_tp_traverse, CDataType_traverse}, {Py_tp_clear, CDataType_clear}, {Py_tp_methods, PyCPointerType_methods}, - {Py_tp_new, PyCPointerType_new}, + {Py_tp_init, PyCPointerType_init}, // Sequence protocol. {Py_sq_repeat, CDataType_repeat}, @@ -1403,8 +1378,8 @@ PyCArrayType_paramfunc(CDataObject *self) return p; } -static PyObject * -PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int +PyCArrayType_init(PyObject *self, PyObject *args, PyObject *kwds) { PyTypeObject *result; StgDictObject *stgdict; @@ -1415,9 +1390,7 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) /* create the new instance (which is a class, since we are a metatype!) */ - result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds); - if (result == NULL) - return NULL; + result = (PyTypeObject *)self; // by PyType_Type.tp_new() /* Initialize these variables to NULL so that we can simplify error handling by using Py_XDECREF. */ @@ -1536,19 +1509,18 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) goto error; } - return (PyObject *)result; + return 0; error: Py_XDECREF((PyObject*)stgdict); Py_XDECREF(type_attr); - Py_DECREF(result); - return NULL; + return -1; } 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_new, PyCArrayType_new}, + {Py_tp_init, PyCArrayType_init}, {Py_tp_clear, CDataType_clear}, // Sequence protocol. @@ -1948,8 +1920,8 @@ PyCSimpleType_paramfunc(CDataObject *self) return parg; } -static PyObject * -PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int +PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds) { PyTypeObject *result; StgDictObject *stgdict; @@ -1961,20 +1933,17 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) /* create the new instance (which is a class, since we are a metatype!) */ - result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds); - if (result == NULL) - return NULL; + result = (PyTypeObject *)self; // by PyType_Type.tp_new() if (PyObject_GetOptionalAttr((PyObject *)result, &_Py_ID(_type_), &proto) < 0) { - return NULL; + return -1; } if (!proto) { PyErr_SetString(PyExc_AttributeError, "class must define a '_type_' attribute"); error: Py_XDECREF(proto); - Py_DECREF(result); - return NULL; + return -1; } if (PyUnicode_Check(proto)) { proto_str = PyUnicode_AsUTF8AndSize(proto, &proto_len); @@ -2023,10 +1992,9 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) stgdict->format = _ctypes_alloc_format_string_for_type(proto_str[0], 0); #endif if (stgdict->format == NULL) { - Py_DECREF(result); Py_DECREF(proto); Py_DECREF((PyObject *)stgdict); - return NULL; + return -1; } stgdict->paramfunc = PyCSimpleType_paramfunc; @@ -2042,9 +2010,8 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) /* replace the class dict by our updated spam dict */ if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) { - Py_DECREF(result); Py_DECREF((PyObject *)stgdict); - return NULL; + return -1; } Py_SETREF(result->tp_dict, (PyObject *)stgdict); @@ -2081,20 +2048,19 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) int x; meth = PyDescr_NewClassMethod(result, ml); if (!meth) { - Py_DECREF(result); - return NULL; + return -1; } x = PyDict_SetItemString(result->tp_dict, ml->ml_name, meth); Py_DECREF(meth); if (x == -1) { - Py_DECREF(result); - return NULL; + return -1; } } } + PyTypeObject *type = Py_TYPE(self); if (type == st->PyCSimpleType_Type && fmt->setfunc_swapped && fmt->getfunc_swapped) @@ -2103,8 +2069,7 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) proto, fmt); StgDictObject *sw_dict; if (swapped == NULL) { - Py_DECREF(result); - return NULL; + return -1; } sw_dict = PyType_stgdict(swapped); #ifdef WORDS_BIGENDIAN @@ -2124,12 +2089,11 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) #endif Py_DECREF(swapped); if (PyErr_Occurred()) { - Py_DECREF(result); - return NULL; + return -1; } }; - return (PyObject *)result; + return 0; } /* @@ -2218,7 +2182,7 @@ static PyMethodDef PyCSimpleType_methods[] = { static PyType_Slot pycsimple_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for the PyCSimpleType Objects")}, {Py_tp_methods, PyCSimpleType_methods}, - {Py_tp_new, PyCSimpleType_new}, + {Py_tp_init, PyCSimpleType_init}, {Py_tp_traverse, CDataType_traverse}, {Py_tp_clear, CDataType_clear}, @@ -2426,8 +2390,8 @@ PyCFuncPtrType_paramfunc(CDataObject *self) return parg; } -static PyObject * -PyCFuncPtrType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int +PyCFuncPtrType_init(PyObject *self, PyObject *args, PyObject *kwds) { PyTypeObject *result; StgDictObject *stgdict; @@ -2436,7 +2400,7 @@ PyCFuncPtrType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) stgdict = (StgDictObject *)_PyObject_CallNoArgs( (PyObject *)st->PyCStgDict_Type); if (!stgdict) { - return NULL; + return -1; } stgdict->paramfunc = PyCFuncPtrType_paramfunc; /* We do NOT expose the function signature in the format string. It @@ -2448,32 +2412,26 @@ PyCFuncPtrType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) stgdict->format = _ctypes_alloc_format_string(NULL, "X{}"); if (stgdict->format == NULL) { Py_DECREF((PyObject *)stgdict); - return NULL; + return -1; } stgdict->flags |= TYPEFLAG_ISPOINTER; /* create the new instance (which is a class, since we are a metatype!) */ - result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds); - if (result == NULL) { - Py_DECREF((PyObject *)stgdict); - return NULL; - } + result = (PyTypeObject *)self; // by PyType_Type.tp_new() /* replace the class dict by our updated storage dict */ if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) { - Py_DECREF(result); Py_DECREF((PyObject *)stgdict); - return NULL; + return -1; } Py_SETREF(result->tp_dict, (PyObject *)stgdict); if (-1 == make_funcptrtype_dict(stgdict)) { - Py_DECREF(result); - return NULL; + return -1; } - return (PyObject *)result; + return 0; } static PyType_Slot pycfuncptr_type_slots[] = { @@ -2481,7 +2439,7 @@ static PyType_Slot pycfuncptr_type_slots[] = { {Py_tp_traverse, CDataType_traverse}, {Py_tp_clear, CDataType_clear}, {Py_tp_methods, CDataType_methods}, - {Py_tp_new, PyCFuncPtrType_new}, + {Py_tp_init, PyCFuncPtrType_init}, // Sequence protocol. {Py_sq_repeat, CDataType_repeat}, @@ -2607,6 +2565,7 @@ KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep) static int PyCData_traverse(CDataObject *self, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(self)); Py_VISIT(self->b_objects); Py_VISIT((PyObject *)self->b_base); return 0; @@ -2627,8 +2586,11 @@ PyCData_clear(CDataObject *self) static void PyCData_dealloc(PyObject *self) { + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); PyCData_clear((CDataObject *)self); - Py_TYPE(self)->tp_free(self); + tp->tp_free(self); + Py_DECREF(tp); } static PyMemberDef PyCData_members[] = { @@ -2690,11 +2652,6 @@ PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags) return 0; } -static PyBufferProcs PyCData_as_buffer = { - PyCData_NewGetBuffer, - NULL, -}; - /* * CData objects are mutable, so they cannot be hashable! */ @@ -2773,46 +2730,25 @@ static PyMethodDef PyCData_methods[] = { { NULL, NULL }, }; -PyTypeObject PyCData_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ctypes._CData", - sizeof(CDataObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - PyCData_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - PyCData_nohash, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - &PyCData_as_buffer, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - PyDoc_STR("XXX to be provided"), /* tp_doc */ - (traverseproc)PyCData_traverse, /* tp_traverse */ - (inquiry)PyCData_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyCData_methods, /* tp_methods */ - PyCData_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot pycdata_slots[] = { + {Py_tp_hash, PyCData_nohash}, + {Py_tp_dealloc, PyCData_dealloc}, + {Py_tp_traverse, PyCData_traverse}, + {Py_tp_clear, PyCData_clear}, + {Py_tp_methods, PyCData_methods}, + {Py_tp_members, PyCData_members}, + + // Buffer Protocol. + {Py_bf_getbuffer, PyCData_NewGetBuffer}, + {0, NULL}, +}; + +static PyType_Spec pycdata_spec = { + .name = "_ctypes._CData", + .basicsize = sizeof(CDataObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = pycdata_slots, }; static int PyCData_MallocBuffer(CDataObject *obj, StgDictObject *dict) @@ -4123,8 +4059,11 @@ PyCFuncPtr_clear(PyCFuncPtrObject *self) static void PyCFuncPtr_dealloc(PyCFuncPtrObject *self) { + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); PyCFuncPtr_clear(self); - Py_TYPE(self)->tp_free((PyObject *)self); + tp->tp_free(self); + Py_DECREF(tp); } static PyObject * @@ -4152,59 +4091,30 @@ PyCFuncPtr_bool(PyCFuncPtrObject *self) ); } -static PyNumberMethods PyCFuncPtr_as_number = { - 0, /* nb_add */ - 0, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - (inquiry)PyCFuncPtr_bool, /* nb_bool */ +static PyType_Slot pycfuncptr_slots[] = { + {Py_tp_doc, PyDoc_STR("Function Pointer")}, + {Py_tp_repr, PyCFuncPtr_repr}, + {Py_tp_call, PyCFuncPtr_call}, + {Py_tp_dealloc, PyCFuncPtr_dealloc}, + {Py_tp_traverse, PyCFuncPtr_traverse}, + {Py_tp_clear, PyCFuncPtr_clear}, + {Py_tp_getset, PyCFuncPtr_getsets}, + {Py_tp_new, PyCFuncPtr_new}, + + // Buffer Protocol. + {Py_bf_getbuffer, PyCData_NewGetBuffer}, + + // Number Protocol. + {Py_nb_bool, PyCFuncPtr_bool}, + {0, NULL}, }; -PyTypeObject PyCFuncPtr_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ctypes.CFuncPtr", - sizeof(PyCFuncPtrObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)PyCFuncPtr_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)PyCFuncPtr_repr, /* tp_repr */ - &PyCFuncPtr_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - (ternaryfunc)PyCFuncPtr_call, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - &PyCData_as_buffer, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - PyDoc_STR("Function Pointer"), /* tp_doc */ - (traverseproc)PyCFuncPtr_traverse, /* tp_traverse */ - (inquiry)PyCFuncPtr_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - PyCFuncPtr_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyCFuncPtr_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Spec pycfuncptr_spec = { + .name = "_ctypes.CFuncPtr", + .basicsize = sizeof(PyCFuncPtrObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = pycfuncptr_slots, }; /*****************************************************************/ @@ -4316,88 +4226,46 @@ Struct_init(PyObject *self, PyObject *args, PyObject *kwds) return 0; } -static PyTypeObject Struct_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ctypes.Structure", - sizeof(CDataObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - &PyCData_as_buffer, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - PyDoc_STR("Structure base class"), /* tp_doc */ - (traverseproc)PyCData_traverse, /* tp_traverse */ - (inquiry)PyCData_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - Struct_init, /* tp_init */ - 0, /* tp_alloc */ - GenericPyCData_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot struct_slots[] = { + {Py_tp_doc, PyDoc_STR("Structure base class")}, + {Py_tp_dealloc, PyCData_dealloc}, + {Py_tp_traverse, PyCData_traverse}, + {Py_tp_clear, PyCData_clear}, + {Py_tp_init, Struct_init}, + {Py_tp_new, GenericPyCData_new}, + + // Buffer Protocol. + {Py_bf_getbuffer, PyCData_NewGetBuffer}, + {0, NULL}, +}; + +static PyType_Spec struct_spec = { + .name = "_ctypes.Structure", + .basicsize = sizeof(CDataObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = struct_slots, }; -static PyTypeObject Union_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ctypes.Union", - sizeof(CDataObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - &PyCData_as_buffer, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - PyDoc_STR("Union base class"), /* tp_doc */ - (traverseproc)PyCData_traverse, /* tp_traverse */ - (inquiry)PyCData_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - Struct_init, /* tp_init */ - 0, /* tp_alloc */ - GenericPyCData_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot union_slots[] = { + {Py_tp_doc, PyDoc_STR("Union base class")}, + {Py_tp_dealloc, PyCData_dealloc}, + {Py_tp_traverse, PyCData_traverse}, + {Py_tp_clear, PyCData_clear}, + {Py_tp_init, Struct_init}, + {Py_tp_new, GenericPyCData_new}, + + // Buffer Protocol. + {Py_bf_getbuffer, PyCData_NewGetBuffer}, + {0, NULL}, +}; + +static PyType_Spec union_spec = { + .name = "_ctypes.Union", + .basicsize = sizeof(CDataObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = union_slots, }; @@ -4658,26 +4526,6 @@ static PyMethodDef Array_methods[] = { { NULL, NULL } }; -static PySequenceMethods Array_as_sequence = { - Array_length, /* sq_length; */ - 0, /* sq_concat; */ - 0, /* sq_repeat; */ - Array_item, /* sq_item; */ - 0, /* sq_slice; */ - Array_ass_item, /* sq_ass_item; */ - 0, /* sq_ass_slice; */ - 0, /* sq_contains; */ - - 0, /* sq_inplace_concat; */ - 0, /* sq_inplace_repeat; */ -}; - -static PyMappingMethods Array_as_mapping = { - Array_length, - Array_subscript, - Array_ass_subscript, -}; - PyDoc_STRVAR(array_doc, "Abstract base class for arrays.\n" "\n" @@ -4688,46 +4536,36 @@ PyDoc_STRVAR(array_doc, "reads, the resulting object is not itself an Array." ); -PyTypeObject PyCArray_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ctypes.Array", - sizeof(CDataObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - &Array_as_sequence, /* tp_as_sequence */ - &Array_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - &PyCData_as_buffer, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - array_doc, /* tp_doc */ - (traverseproc)PyCData_traverse, /* tp_traverse */ - (inquiry)PyCData_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Array_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)Array_init, /* tp_init */ - 0, /* tp_alloc */ - GenericPyCData_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot array_slots[] = { + {Py_tp_doc, (void *)array_doc}, + {Py_tp_dealloc, PyCData_dealloc}, + {Py_tp_traverse, PyCData_traverse}, + {Py_tp_clear, PyCData_clear}, + {Py_tp_methods, Array_methods}, + {Py_tp_init, Array_init}, + {Py_tp_new, GenericPyCData_new}, + + // Buffer Protocol. + {Py_bf_getbuffer, PyCData_NewGetBuffer}, + + // Mapping protocol + {Py_mp_length, Array_length}, + {Py_mp_subscript, Array_subscript}, + {Py_mp_ass_subscript, Array_ass_subscript}, + + // Sequence protocol. + {Py_sq_length, Array_length}, + {Py_sq_item, Array_item}, + {Py_sq_ass_item, Array_ass_item}, + {0, NULL}, +}; + +static PyType_Spec array_spec = { + .name = "_ctypes.Array", + .basicsize = sizeof(CDataObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = array_slots, }; PyObject * @@ -4868,19 +4706,6 @@ static int Simple_bool(CDataObject *self) return memcmp(self->b_ptr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", self->b_size); } -static PyNumberMethods Simple_as_number = { - 0, /* nb_add */ - 0, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - (inquiry)Simple_bool, /* nb_bool */ -}; - /* "%s(%s)" % (self.__class__.__name__, self.value) */ static PyObject * Simple_repr(CDataObject *self) @@ -4903,46 +4728,31 @@ Simple_repr(CDataObject *self) return result; } -static PyTypeObject Simple_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ctypes._SimpleCData", - sizeof(CDataObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)&Simple_repr, /* tp_repr */ - &Simple_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - &PyCData_as_buffer, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - PyDoc_STR("XXX to be provided"), /* tp_doc */ - (traverseproc)PyCData_traverse, /* tp_traverse */ - (inquiry)PyCData_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Simple_methods, /* tp_methods */ - 0, /* tp_members */ - Simple_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)Simple_init, /* tp_init */ - 0, /* tp_alloc */ - GenericPyCData_new, /* tp_new */ - 0, /* tp_free */ + +static PyType_Slot simple_slots[] = { + {Py_tp_repr, Simple_repr}, + {Py_tp_dealloc, PyCData_dealloc}, + {Py_tp_traverse, PyCData_traverse}, + {Py_tp_clear, PyCData_clear}, + {Py_tp_methods, Simple_methods}, + {Py_tp_getset, Simple_getsets}, + {Py_tp_init, Simple_init}, + {Py_tp_new, GenericPyCData_new}, + + // Buffer Protocol. + {Py_bf_getbuffer, PyCData_NewGetBuffer}, + + // Number Protocol. + {Py_nb_bool, Simple_bool}, + {0, NULL}, +}; + +static PyType_Spec simple_spec = { + .name = "_ctypes._SimpleCData", + .basicsize = sizeof(CDataObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = simple_slots, }; /******************************************************************/ @@ -5248,84 +5058,41 @@ Pointer_subscript(PyObject *myself, PyObject *item) } } -static PySequenceMethods Pointer_as_sequence = { - 0, /* inquiry sq_length; */ - 0, /* binaryfunc sq_concat; */ - 0, /* intargfunc sq_repeat; */ - Pointer_item, /* intargfunc sq_item; */ - 0, /* intintargfunc sq_slice; */ - Pointer_ass_item, /* intobjargproc sq_ass_item; */ - 0, /* intintobjargproc sq_ass_slice; */ - 0, /* objobjproc sq_contains; */ - /* Added in release 2.0 */ - 0, /* binaryfunc sq_inplace_concat; */ - 0, /* intargfunc sq_inplace_repeat; */ -}; - -static PyMappingMethods Pointer_as_mapping = { - 0, - Pointer_subscript, -}; - static int Pointer_bool(CDataObject *self) { return (*(void **)self->b_ptr != NULL); } -static PyNumberMethods Pointer_as_number = { - 0, /* nb_add */ - 0, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - (inquiry)Pointer_bool, /* nb_bool */ +static PyType_Slot pointer_slots[] = { + {Py_tp_dealloc, PyCData_dealloc}, + {Py_tp_traverse, PyCData_traverse}, + {Py_tp_clear, PyCData_clear}, + {Py_tp_getset, Pointer_getsets}, + {Py_tp_init, Pointer_init}, + {Py_tp_new, Pointer_new}, + + // Buffer Protocol. + {Py_bf_getbuffer, PyCData_NewGetBuffer}, + + // Mapping protocol. + {Py_mp_subscript, Pointer_subscript}, + + // Number Protocol. + {Py_nb_bool, Pointer_bool}, + + // Sequence protocol. + {Py_sq_item, Pointer_item}, + {Py_sq_ass_item, Pointer_ass_item}, + {0, NULL}, }; -PyTypeObject PyCPointer_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ctypes._Pointer", - sizeof(CDataObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - &Pointer_as_number, /* tp_as_number */ - &Pointer_as_sequence, /* tp_as_sequence */ - &Pointer_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - &PyCData_as_buffer, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - PyDoc_STR("XXX to be provided"), /* tp_doc */ - (traverseproc)PyCData_traverse, /* tp_traverse */ - (inquiry)PyCData_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - Pointer_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)Pointer_init, /* tp_init */ - 0, /* tp_alloc */ - Pointer_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Spec pointer_spec = { + .name = "_ctypes._Pointer", + .basicsize = sizeof(CDataObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = pointer_slots, }; @@ -5552,15 +5319,18 @@ _ctypes_add_types(PyObject *mod) TYPE_READY(type); \ } while (0) -#define MOD_ADD_TYPE(TYPE_EXPR, TP_TYPE, TP_BASE) \ - do { \ - PyTypeObject *type = (TYPE_EXPR); \ - Py_SET_TYPE(type, TP_TYPE); \ - type->tp_base = TP_BASE; \ - if (PyModule_AddType(mod, type) < 0) { \ - return -1; \ - } \ - } while (0) +#define MOD_ADD_TYPE(TP, SPEC, TP_TYPE) do { \ + PyObject *type = PyType_FromMetaclass(TP_TYPE, mod, SPEC, \ + (PyObject *)st->PyCData_Type); \ + if (type == NULL) { \ + return -1; \ + } \ + if (PyModule_AddType(mod, (PyTypeObject *)type) < 0) { \ + Py_DECREF(type); \ + return -1; \ + } \ + TP = (PyTypeObject *)type; \ +} while (0) #define CREATE_TYPE(MOD, TP, SPEC, BASE) do { \ PyObject *type = PyType_FromMetaclass(NULL, MOD, SPEC, \ @@ -5579,7 +5349,7 @@ _ctypes_add_types(PyObject *mod) */ CREATE_TYPE(mod, st->PyCArg_Type, &carg_spec, NULL); CREATE_TYPE(mod, st->PyCThunk_Type, &cthunk_spec, NULL); - TYPE_READY(st->PyCData_Type); + CREATE_TYPE(mod, st->PyCData_Type, &pycdata_spec, NULL); /* StgDict is derived from PyDict_Type */ TYPE_READY_BASE(st->PyCStgDict_Type, &PyDict_Type); @@ -5604,12 +5374,12 @@ _ctypes_add_types(PyObject *mod) * Classes using a custom metaclass */ - MOD_ADD_TYPE(st->Struct_Type, st->PyCStructType_Type, st->PyCData_Type); - MOD_ADD_TYPE(st->Union_Type, st->UnionType_Type, st->PyCData_Type); - MOD_ADD_TYPE(st->PyCPointer_Type, st->PyCPointerType_Type, st->PyCData_Type); - MOD_ADD_TYPE(st->PyCArray_Type, st->PyCArrayType_Type, st->PyCData_Type); - MOD_ADD_TYPE(st->Simple_Type, st->PyCSimpleType_Type, st->PyCData_Type); - MOD_ADD_TYPE(st->PyCFuncPtr_Type, st->PyCFuncPtrType_Type, st->PyCData_Type); + MOD_ADD_TYPE(st->Struct_Type, &struct_spec, st->PyCStructType_Type); + MOD_ADD_TYPE(st->Union_Type, &union_spec, st->UnionType_Type); + MOD_ADD_TYPE(st->PyCPointer_Type, &pointer_spec, st->PyCPointerType_Type); + MOD_ADD_TYPE(st->PyCArray_Type, &array_spec, st->PyCArrayType_Type); + MOD_ADD_TYPE(st->Simple_Type, &simple_spec, st->PyCSimpleType_Type); + MOD_ADD_TYPE(st->PyCFuncPtr_Type, &pycfuncptr_spec, st->PyCFuncPtrType_Type); /************************************************* * diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 1989723f6f3dbb..56fa29238c8ff3 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -164,7 +164,6 @@ extern int PyObject_stginfo(PyObject *self, Py_ssize_t *psize, Py_ssize_t *palig -extern PyTypeObject PyCData_Type; #define CDataObject_CheckExact(st, v) Py_IS_TYPE((v), (st)->PyCData_Type) #define CDataObject_Check(st, v) PyObject_TypeCheck((v), (st)->PyCData_Type) #define _CDataObject_HasExternalBuffer(v) ((v)->b_ptr != (char *)&(v)->b_value) @@ -184,10 +183,6 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index, extern PyObject *PyCData_AtAddress(PyObject *type, void *buf); extern PyObject *PyCData_FromBytes(PyObject *type, char *data, Py_ssize_t length); -extern PyTypeObject PyCArray_Type; -extern PyTypeObject PyCPointer_Type; -extern PyTypeObject PyCFuncPtr_Type; - #define PyCArrayTypeObject_Check(st, v) PyObject_TypeCheck((v), (st)->PyCArrayType_Type) #define ArrayObject_Check(st, v) PyObject_TypeCheck((v), (st)->PyCArray_Type) #define PointerObject_Check(st, v) PyObject_TypeCheck((v), (st)->PyCPointer_Type)