From 9f64b8d965a386411555d058c653a4394397331c Mon Sep 17 00:00:00 2001 From: neonene Date: Sat, 23 Mar 2024 22:13:29 +0900 Subject: [PATCH 01/38] add test --- Lib/test/test_ctypes/test_refcounts.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Lib/test/test_ctypes/test_refcounts.py b/Lib/test/test_ctypes/test_refcounts.py index a90588ca9bb1b6..6a7bbbf1b1f57a 100644 --- a/Lib/test/test_ctypes/test_refcounts.py +++ b/Lib/test/test_ctypes/test_refcounts.py @@ -4,6 +4,7 @@ import sys import unittest from test import support +from test.support import script_helper MyCallback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int) @@ -109,5 +110,18 @@ def func(): func() +class ModuleIsolationTest(unittest.TestCase): + def test_finalize(self): + # check if gc_decref() succeeds + script = ( + "import ctypes;" + "import sys;" + "del sys.modules['_ctypes'];" + "import _ctypes;" + "exit()" + ) + script_helper.assert_python_ok("-c", script) + + if __name__ == '__main__': unittest.main() From 22d291c912785e81aa4a5342365b295144229531 Mon Sep 17 00:00:00 2001 From: neonene Date: Sat, 23 Mar 2024 22:22:32 +0900 Subject: [PATCH 02/38] multi phase init --- Modules/_ctypes/_ctypes.c | 194 ++++++++++++++++++++++++++------------ Modules/_ctypes/ctypes.h | 36 ++++++- 2 files changed, 168 insertions(+), 62 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index af094a0fb59e27..e185409ec9fa10 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -126,17 +126,6 @@ bytes(cdata) #include "pycore_long.h" // _PyLong_GetZero() -ctypes_state global_state = {0}; - -PyObject *PyExc_ArgError = NULL; - -/* This dict maps ctypes types to POINTER types */ -PyObject *_ctypes_ptrtype_cache = NULL; - -/* a callable object used for unpickling: - strong reference to _ctypes._unpickle() function */ -static PyObject *_unpickle; - /****************************************************************/ @@ -469,7 +458,9 @@ _ctype_clear_stginfo(StgInfo *info) static int CType_Type_clear(PyObject *self) { - ctypes_state *st = GLOBAL_STATE(); + PyTypeObject *type = Py_TYPE(self); + ctypes_state *st = type->tp_mro ? get_module_state_by_def(type) : NULL; + if (st && st->PyCType_Type) { StgInfo *info; if (PyStgInfo_FromType(st, self, &info) < 0) { @@ -485,7 +476,8 @@ CType_Type_clear(PyObject *self) static void CType_Type_dealloc(PyObject *self) { - ctypes_state *st = GLOBAL_STATE(); + PyTypeObject *type = Py_TYPE(self); + ctypes_state *st = type->tp_mro ? get_module_state_by_def(type) : NULL; if (st && st->PyCType_Type) { StgInfo *info; @@ -503,9 +495,8 @@ CType_Type_dealloc(PyObject *self) } } - PyTypeObject *tp = Py_TYPE(self); PyType_Type.tp_dealloc(self); - Py_DECREF(tp); + Py_DECREF(type); } static PyObject * @@ -996,13 +987,17 @@ CDataType_repeat(PyObject *self, Py_ssize_t 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); + PyTypeObject *type = Py_TYPE(self); + ctypes_state *st = type->tp_mro ? get_module_state_by_def(type) : NULL; + + if (st && st->PyCType_Type) { + 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); } @@ -1010,15 +1005,19 @@ CDataType_clear(PyTypeObject *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); + PyTypeObject *type = Py_TYPE(self); + ctypes_state *st = type->tp_mro ? get_module_state_by_def(type) : NULL; + + if (st && st->PyCType_Type) { + StgInfo *info; + if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) { + return -1; + } + if (info) { + Py_VISIT(info->proto); + } } - Py_VISIT(Py_TYPE(self)); + Py_VISIT(type); return PyType_Type.tp_traverse((PyObject *)self, visit, arg); } @@ -5535,15 +5534,6 @@ wstring_at(const wchar_t *ptr, int size) } -static struct PyModuleDef _ctypesmodule = { - PyModuleDef_HEAD_INIT, - .m_name = "_ctypes", - .m_doc = _ctypes__doc__, - .m_size = -1, - .m_methods = _ctypes_module_methods, -}; - - static int _ctypes_add_types(PyObject *mod) { @@ -5567,7 +5557,7 @@ _ctypes_add_types(PyObject *mod) } \ } while (0) - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state(mod); /* Note: ob_type is the metatype (the 'type'), defaults to PyType_Type, @@ -5652,10 +5642,10 @@ _ctypes_add_objects(PyObject *mod) } \ } while (0) - MOD_ADD("_pointer_type_cache", Py_NewRef(_ctypes_ptrtype_cache)); + ctypes_state *st = get_module_state(mod); + MOD_ADD("_pointer_type_cache", Py_NewRef(st->_ctypes_ptrtype_cache)); #ifdef MS_WIN32 - ctypes_state *st = GLOBAL_STATE(); MOD_ADD("COMError", Py_NewRef(st->PyComError_Type)); MOD_ADD("FUNCFLAG_HRESULT", PyLong_FromLong(FUNCFLAG_HRESULT)); MOD_ADD("FUNCFLAG_STDCALL", PyLong_FromLong(FUNCFLAG_STDCALL)); @@ -5685,7 +5675,7 @@ _ctypes_add_objects(PyObject *mod) MOD_ADD("RTLD_LOCAL", PyLong_FromLong(RTLD_LOCAL)); MOD_ADD("RTLD_GLOBAL", PyLong_FromLong(RTLD_GLOBAL)); MOD_ADD("CTYPES_MAX_ARGCOUNT", PyLong_FromLong(CTYPES_MAX_ARGCOUNT)); - MOD_ADD("ArgumentError", Py_NewRef(PyExc_ArgError)); + MOD_ADD("ArgumentError", Py_NewRef(st->PyExc_ArgError)); MOD_ADD("SIZEOF_TIME_T", PyLong_FromSsize_t(SIZEOF_TIME_T)); return 0; #undef MOD_ADD @@ -5695,18 +5685,19 @@ _ctypes_add_objects(PyObject *mod) static int _ctypes_mod_exec(PyObject *mod) { - _unpickle = PyObject_GetAttrString(mod, "_unpickle"); - if (_unpickle == NULL) { + ctypes_state *st = get_module_state(mod); + st->_unpickle = PyObject_GetAttrString(mod, "_unpickle"); + if (st->_unpickle == NULL) { return -1; } - _ctypes_ptrtype_cache = PyDict_New(); - if (_ctypes_ptrtype_cache == NULL) { + st->_ctypes_ptrtype_cache = PyDict_New(); + if (st->_ctypes_ptrtype_cache == NULL) { return -1; } - PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL); - if (!PyExc_ArgError) { + st->PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL); + if (!st->PyExc_ArgError) { return -1; } @@ -5721,19 +5712,104 @@ _ctypes_mod_exec(PyObject *mod) } +static int +module_traverse(PyObject *module, visitproc visit, void *arg) { + ctypes_state *st = get_module_state(module); + Py_VISIT(st->_ctypes_ptrtype_cache); + Py_VISIT(st->_unpickle); + Py_VISIT(st->array_cache); + Py_VISIT(st->error_object_name); + Py_VISIT(st->PyExc_ArgError); + Py_VISIT(st->swapped_suffix); + + Py_VISIT(st->DictRemover_Type); + Py_VISIT(st->PyCArg_Type); + Py_VISIT(st->PyCField_Type); + Py_VISIT(st->PyCThunk_Type); + Py_VISIT(st->StructParam_Type); + Py_VISIT(st->PyCStructType_Type); + Py_VISIT(st->UnionType_Type); + Py_VISIT(st->PyCPointerType_Type); + Py_VISIT(st->PyCArrayType_Type); + Py_VISIT(st->PyCSimpleType_Type); + Py_VISIT(st->PyCFuncPtrType_Type); + Py_VISIT(st->PyCData_Type); + Py_VISIT(st->Struct_Type); + Py_VISIT(st->Union_Type); + Py_VISIT(st->PyCArray_Type); + Py_VISIT(st->Simple_Type); + Py_VISIT(st->PyCPointer_Type); + Py_VISIT(st->PyCFuncPtr_Type); +#ifdef MS_WIN32 + Py_VISIT(st->PyComError_Type); +#endif + Py_VISIT(st->PyCType_Type); + return 0; +} + +static int +module_clear(PyObject *module) { + ctypes_state *st = get_module_state(module); + Py_CLEAR(st->_ctypes_ptrtype_cache); + Py_CLEAR(st->_unpickle); + Py_CLEAR(st->array_cache); + Py_CLEAR(st->error_object_name); + Py_CLEAR(st->PyExc_ArgError); + Py_CLEAR(st->swapped_suffix); + + Py_CLEAR(st->DictRemover_Type); + Py_CLEAR(st->PyCArg_Type); + Py_CLEAR(st->PyCField_Type); + Py_CLEAR(st->PyCThunk_Type); + Py_CLEAR(st->StructParam_Type); + Py_CLEAR(st->PyCStructType_Type); + Py_CLEAR(st->UnionType_Type); + Py_CLEAR(st->PyCPointerType_Type); + Py_CLEAR(st->PyCArrayType_Type); + Py_CLEAR(st->PyCSimpleType_Type); + Py_CLEAR(st->PyCFuncPtrType_Type); + Py_CLEAR(st->PyCData_Type); + Py_CLEAR(st->Struct_Type); + Py_CLEAR(st->Union_Type); + Py_CLEAR(st->PyCArray_Type); + Py_CLEAR(st->Simple_Type); + Py_CLEAR(st->PyCPointer_Type); + Py_CLEAR(st->PyCFuncPtr_Type); +#ifdef MS_WIN32 + Py_CLEAR(st->PyComError_Type); +#endif + Py_CLEAR(st->PyCType_Type); + return 0; +} + +static void +module_free(void *module) +{ + (void)module_clear((PyObject *)module); +} + +static PyModuleDef_Slot module_slots[] = { + {Py_mod_exec, _ctypes_mod_exec}, + {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {0, NULL} +}; + +struct PyModuleDef _ctypesmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "_ctypes", + .m_doc = _ctypes__doc__, + .m_size = sizeof(ctypes_state), + .m_methods = _ctypes_module_methods, + .m_slots = module_slots, + .m_traverse = module_traverse, + .m_clear = module_clear, + .m_free = module_free, +}; + PyMODINIT_FUNC PyInit__ctypes(void) { - PyObject *mod = PyModule_Create(&_ctypesmodule); - if (!mod) { - return NULL; - } - - if (_ctypes_mod_exec(mod) < 0) { - Py_DECREF(mod); - return NULL; - } - return mod; + return PyModuleDef_Init(&_ctypesmodule); } /* diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index d7d725a4fdf669..b5a4fe2c3bb20e 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -2,6 +2,9 @@ # include #endif +#include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_typeobject.h" // _PyType_GetModuleState() + #ifndef MS_WIN32 #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) @@ -42,6 +45,7 @@ typedef struct { PyTypeObject *PyCField_Type; PyTypeObject *PyCThunk_Type; PyTypeObject *StructParam_Type; + PyTypeObject *PyCType_Type; PyTypeObject *PyCStructType_Type; PyTypeObject *UnionType_Type; PyTypeObject *PyCPointerType_Type; @@ -58,12 +62,38 @@ typedef struct { #ifdef MS_WIN32 PyTypeObject *PyComError_Type; #endif - PyTypeObject *PyCType_Type; + /* This dict maps ctypes types to POINTER types */ + PyObject *_ctypes_ptrtype_cache; + /* a callable object used for unpickling: + strong reference to _ctypes._unpickle() function */ + PyObject *_unpickle; + PyObject *array_cache; + PyObject *error_object_name; // callproc.c + PyObject *PyExc_ArgError; + PyObject *swapped_suffix; } ctypes_state; -extern ctypes_state global_state; -#define GLOBAL_STATE() (&global_state) +extern PyModuleDef _ctypesmodule; + + +static inline ctypes_state * +get_module_state(PyObject *module) { + void *state = _PyModule_GetState(module); + assert(state != NULL); + return (ctypes_state *)state; +} + +static inline ctypes_state * +get_module_state_by_def(PyTypeObject *cls) +{ + // NOTE: class's tp_mro slot can be cleared by the GC during a module + // finalization, which PyType_GetModuleByDef() does not expect. + PyObject *mod = PyType_GetModuleByDef(cls, &_ctypesmodule); + assert(mod != NULL); + return get_module_state(mod); +} + extern PyType_Spec carg_spec; extern PyType_Spec cfield_spec; From c63737e0ca22636d5191923f81d64f51bab066b2 Mon Sep 17 00:00:00 2001 From: neonene Date: Sat, 23 Mar 2024 22:29:45 +0900 Subject: [PATCH 03/38] _PyType_GetModuleState() for CField,CThunk --- Modules/_ctypes/callbacks.c | 4 +++- Modules/_ctypes/cfield.c | 8 ++++---- Modules/_ctypes/stgdict.c | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 08d068e47ee2bf..9fa2e18afc313e 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -303,8 +303,10 @@ static void closure_fcn(ffi_cif *cif, void *userdata) { CThunkObject *p = (CThunkObject *)userdata; + ctypes_state *st = _PyType_GetModuleState(Py_TYPE(p)); - _CallPythonObject(resp, + _CallPythonObject(st, + resp, p->ffi_restype, p->setfunc, p->callable, diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 16b66382bfe33f..85305ca2b58b9c 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -217,7 +217,7 @@ PyCField_set(CFieldObject *self, PyObject *inst, PyObject *value) { CDataObject *dst; char *ptr; - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = _PyType_GetModuleState(Py_TYPE(self)); if (!CDataObject_Check(st, inst)) { PyErr_SetString(PyExc_TypeError, "not a ctype instance"); @@ -230,7 +230,7 @@ PyCField_set(CFieldObject *self, PyObject *inst, PyObject *value) "can't delete attribute"); return -1; } - return PyCData_set(inst, self->proto, self->setfunc, value, + return PyCData_set(st, inst, self->proto, self->setfunc, value, self->index, self->size, ptr); } @@ -241,14 +241,14 @@ PyCField_get(CFieldObject *self, PyObject *inst, PyTypeObject *type) if (inst == NULL) { return Py_NewRef(self); } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = _PyType_GetModuleState(Py_TYPE(self)); if (!CDataObject_Check(st, inst)) { PyErr_SetString(PyExc_TypeError, "not a ctype instance"); return NULL; } src = (CDataObject *)inst; - return PyCData_get(self->proto, self->getfunc, inst, + return PyCData_get(st, self->proto, self->getfunc, inst, self->index, self->size, src->b_ptr + self->offset); } diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 8666ded5c2b3f2..f7905b7f3fb40f 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -92,7 +92,7 @@ MakeFields(PyObject *type, CFieldObject *descr, if (fieldlist == NULL) return -1; - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = _PyType_GetModuleState(Py_TYPE(descr)); PyTypeObject *cfield_tp = st->PyCField_Type; for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) { PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */ From 6a775bc8d33b796ebce929f0a7898cd247c35ec6 Mon Sep 17 00:00:00 2001 From: neonene Date: Sat, 23 Mar 2024 22:31:17 +0900 Subject: [PATCH 04/38] PyType_GetModuleByDef() for cast() --- Modules/_ctypes/_ctypes.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index e185409ec9fa10..d681fdcbd6c464 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -5435,10 +5435,8 @@ string_at(const char *ptr, int size) } static int -cast_check_pointertype(PyObject *arg) +cast_check_pointertype(ctypes_state *st, PyObject *arg) { - ctypes_state *st = GLOBAL_STATE(); - if (PyCPointerTypeObject_Check(st, arg)) { return 1; } @@ -5467,8 +5465,16 @@ cast_check_pointertype(PyObject *arg) static PyObject * cast(void *ptr, PyObject *src, PyObject *ctype) { + PyObject *mod = PyType_GetModuleByDef(Py_TYPE(ctype), &_ctypesmodule); + if (!mod) { + PyErr_SetString(PyExc_TypeError, + "cast() argument 2 must be a pointer type"); + return NULL; + } + ctypes_state *st = get_module_state(mod); + CDataObject *result; - if (0 == cast_check_pointertype(ctype)) + if (0 == cast_check_pointertype(st, ctype)) return NULL; result = (CDataObject *)_PyObject_CallNoArgs(ctype); if (result == NULL) @@ -5480,7 +5486,6 @@ cast(void *ptr, PyObject *src, PyObject *ctype) It must certainly contain the source objects one. It must contain the source object itself. */ - ctypes_state *st = GLOBAL_STATE(); if (CDataObject_Check(st, src)) { CDataObject *obj = (CDataObject *)src; CDataObject *container; From 622e09dc7068aacf110d2215d55f118f224455a9 Mon Sep 17 00:00:00 2001 From: neonene Date: Sat, 23 Mar 2024 22:37:07 +0900 Subject: [PATCH 05/38] get_module_state() --- Modules/_ctypes/callproc.c | 42 +++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 6ebbb64d61b07a..7b5c6b59c8c769 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -202,7 +202,8 @@ static PyObject * get_error_internal(PyObject *self, PyObject *args, int index) { int *space; - PyObject *errobj = _ctypes_get_errobj(&space); + ctypes_state *st = get_module_state(self); + PyObject *errobj = _ctypes_get_errobj(st, &space); PyObject *result; if (errobj == NULL) @@ -222,7 +223,8 @@ set_error_internal(PyObject *self, PyObject *args, int index) if (!PyArg_ParseTuple(args, "i", &new_errno)) { return NULL; } - errobj = _ctypes_get_errobj(&space); + ctypes_state *st = get_module_state(self); + errobj = _ctypes_get_errobj(st, &space); if (errobj == NULL) return NULL; old_errno = space[index]; @@ -1463,7 +1465,8 @@ copy_com_pointer(PyObject *self, PyObject *args) return NULL; a.keep = b.keep = NULL; - if (-1 == ConvParam(p1, 0, &a) || -1 == ConvParam(p2, 1, &b)) + ctypes_state *st = get_module_state(self); + if (-1 == ConvParam(st, p1, 0, &a) || -1 == ConvParam(st, p2, 1, &b)) goto done; src = (IUnknown *)a.value.p; pdst = (IUnknown **)b.value.p; @@ -1643,7 +1646,9 @@ call_function(PyObject *self, PyObject *args) return NULL; } - result = _ctypes_callproc((PPROC)func, + ctypes_state *st = get_module_state(self); + result = _ctypes_callproc(st, + (PPROC)func, arguments, #ifdef MS_WIN32 NULL, @@ -1678,7 +1683,9 @@ call_cdeclfunction(PyObject *self, PyObject *args) return NULL; } - result = _ctypes_callproc((PPROC)func, + ctypes_state *st = get_module_state(self); + result = _ctypes_callproc(st, + (PPROC)func, arguments, #ifdef MS_WIN32 NULL, @@ -1702,7 +1709,7 @@ PyDoc_STRVAR(sizeof_doc, static PyObject * sizeof_func(PyObject *self, PyObject *obj) { - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state(self); StgInfo *info; if (PyStgInfo_FromType(st, obj, &info) < 0) { @@ -1728,7 +1735,7 @@ PyDoc_STRVAR(alignment_doc, static PyObject * align_func(PyObject *self, PyObject *obj) { - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state(self); StgInfo *info; if (PyStgInfo_FromAny(st, obj, &info) < 0) { return NULL; @@ -1766,7 +1773,7 @@ byref(PyObject *self, PyObject *args) if (offset == -1 && PyErr_Occurred()) return NULL; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state(self); if (!CDataObject_Check(st, obj)) { PyErr_Format(PyExc_TypeError, "byref() argument must be a ctypes instance, not '%s'", @@ -1774,7 +1781,7 @@ byref(PyObject *self, PyObject *args) return NULL; } - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) return NULL; @@ -1792,7 +1799,7 @@ PyDoc_STRVAR(addressof_doc, static PyObject * addressof(PyObject *self, PyObject *obj) { - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state(self); if (!CDataObject_Check(st, obj)) { PyErr_SetString(PyExc_TypeError, "invalid type"); @@ -1851,7 +1858,7 @@ resize(PyObject *self, PyObject *args) &obj, &size)) return NULL; - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state(self); StgInfo *info; int result = PyStgInfo_FromObject(st, (PyObject *)obj, &info); if (result < 0) { @@ -1949,11 +1956,11 @@ create_pointer_type(PyObject *module, PyObject *cls) PyTypeObject *typ; PyObject *key; - if (PyDict_GetItemRef(_ctypes_ptrtype_cache, cls, &result) != 0) { + ctypes_state *st = get_module_state(module); + if (PyDict_GetItemRef(st->_ctypes_ptrtype_cache, cls, &result) != 0) { // found or error return result; } - ctypes_state *st = GLOBAL_STATE(); // not found if (PyUnicode_CheckExact(cls)) { PyObject *name = PyUnicode_FromFormat("LP_%U", cls); @@ -1983,7 +1990,7 @@ create_pointer_type(PyObject *module, PyObject *cls) PyErr_SetString(PyExc_TypeError, "must be a ctypes type"); return NULL; } - if (-1 == PyDict_SetItem(_ctypes_ptrtype_cache, key, result)) { + if (-1 == PyDict_SetItem(st->_ctypes_ptrtype_cache, key, result)) { Py_DECREF(result); Py_DECREF(key); return NULL; @@ -2012,11 +2019,12 @@ create_pointer_inst(PyObject *module, PyObject *arg) PyObject *result; PyObject *typ; - if (PyDict_GetItemRef(_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg), &typ) < 0) { + ctypes_state *st = get_module_state(module); + if (PyDict_GetItemRef(st->_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg), &typ) < 0) { return NULL; } if (typ == NULL) { - typ = create_pointer_type(NULL, (PyObject *)Py_TYPE(arg)); + typ = create_pointer_type(module, (PyObject *)Py_TYPE(arg)); if (typ == NULL) return NULL; } @@ -2031,7 +2039,7 @@ buffer_info(PyObject *self, PyObject *arg) PyObject *shape; Py_ssize_t i; - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state(self); StgInfo *info; if (PyStgInfo_FromAny(st, arg, &info) < 0) { return NULL; From 5dae271ccd7c5842ac36591fc5ea3b583cac947c Mon Sep 17 00:00:00 2001 From: neonene Date: Sat, 23 Mar 2024 22:48:00 +0900 Subject: [PATCH 06/38] get_module_state_by_def(Py_TYPE(Py_TYPE(obj))) --- Modules/_ctypes/_ctypes.c | 54 ++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index d681fdcbd6c464..cc8360c177415c 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -2776,14 +2776,14 @@ PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags) { CDataObject *self = (CDataObject *)myself; - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(myself))); StgInfo *info; if (PyStgInfo_FromObject(st, myself, &info) < 0) { return -1; } assert(info); - PyObject *item_type = PyCData_item_type((PyObject*)Py_TYPE(myself)); + PyObject *item_type = PyCData_item_type(st, (PyObject*)Py_TYPE(myself)); if (item_type == NULL) { return 0; } @@ -2826,7 +2826,7 @@ PyCData_reduce(PyObject *myself, PyObject *args) { CDataObject *self = (CDataObject *)myself; - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(myself))); StgInfo *info; if (PyStgInfo_FromObject(st, myself, &info) < 0) { return NULL; @@ -2842,7 +2842,7 @@ PyCData_reduce(PyObject *myself, PyObject *args) if (dict == NULL) { return NULL; } - return Py_BuildValue("O(O(NN))", _unpickle, Py_TYPE(myself), dict, + return Py_BuildValue("O(O(NN))", st->_unpickle, Py_TYPE(myself), dict, PyBytes_FromStringAndSize(self->b_ptr, self->b_size)); } @@ -3276,7 +3276,7 @@ PyCFuncPtr_set_restype(PyCFuncPtrObject *self, PyObject *ob, void *Py_UNUSED(ign Py_XDECREF(oldchecker); return 0; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *info; if (PyStgInfo_FromType(st, ob, &info) < 0) { return -1; @@ -3303,7 +3303,7 @@ PyCFuncPtr_get_restype(PyCFuncPtrObject *self, void *Py_UNUSED(ignored)) if (self->restype) { return Py_NewRef(self->restype); } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *info; if (PyStgInfo_FromObject(st, (PyObject *)self, &info) < 0) { return NULL; @@ -3325,7 +3325,8 @@ PyCFuncPtr_set_argtypes(PyCFuncPtrObject *self, PyObject *ob, void *Py_UNUSED(ig Py_CLEAR(self->converters); Py_CLEAR(self->argtypes); } else { - converters = converters_from_argtypes(ob); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); + converters = converters_from_argtypes(st, ob); if (!converters) return -1; Py_XSETREF(self->converters, converters); @@ -3341,7 +3342,7 @@ PyCFuncPtr_get_argtypes(PyCFuncPtrObject *self, void *Py_UNUSED(ignored)) if (self->argtypes) { return Py_NewRef(self->argtypes); } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *info; if (PyStgInfo_FromObject(st, (PyObject *)self, &info) < 0) { return NULL; @@ -4129,7 +4130,7 @@ PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds) int outmask; unsigned int numretvals; - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *info; if (PyStgInfo_FromObject(st, (PyObject *)self, &info) < 0) { return NULL; @@ -4523,7 +4524,7 @@ Array_item(PyObject *myself, Py_ssize_t index) return NULL; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *stginfo; if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { return NULL; @@ -4535,7 +4536,7 @@ Array_item(PyObject *myself, Py_ssize_t index) size = stginfo->size / stginfo->length; offset = index * size; - return PyCData_get(stginfo->proto, stginfo->getfunc, (PyObject *)self, + return PyCData_get(st, stginfo->proto, stginfo->getfunc, (PyObject *)self, index, size, self->b_ptr + offset); } @@ -4564,7 +4565,7 @@ Array_subscript(PyObject *myself, PyObject *item) } slicelen = PySlice_AdjustIndices(self->b_length, &start, &stop, step); - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *stginfo; if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { return NULL; @@ -4665,7 +4666,7 @@ Array_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value) return -1; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *stginfo; if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { return -1; @@ -4681,7 +4682,7 @@ Array_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value) offset = index * size; ptr = self->b_ptr + offset; - return PyCData_set((PyObject *)self, stginfo->proto, stginfo->setfunc, value, + return PyCData_set(st, (PyObject *)self, stginfo->proto, stginfo->setfunc, value, index, size, ptr); } @@ -4868,7 +4869,7 @@ Simple_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) return -1; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *info; if (PyStgInfo_FromObject(st, (PyObject *)self, &info) < 0) { return -1; @@ -4898,7 +4899,7 @@ Simple_init(CDataObject *self, PyObject *args, PyObject *kw) static PyObject * Simple_get_value(CDataObject *self, void *Py_UNUSED(ignored)) { - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *info; if (PyStgInfo_FromObject(st, (PyObject *)self, &info) < 0) { return NULL; @@ -4917,7 +4918,8 @@ static PyGetSetDef Simple_getsets[] = { static PyObject * Simple_from_outparm(PyObject *self, PyObject *args) { - if (_ctypes_simple_instance((PyObject *)Py_TYPE(self))) { + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); + if (_ctypes_simple_instance(st, (PyObject *)Py_TYPE(self))) { return Py_NewRef(self); } /* call stginfo->getfunc */ @@ -4939,7 +4941,7 @@ static PyObject * Simple_repr(CDataObject *self) { PyObject *val, *result; - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); if (Py_TYPE(self)->tp_base != st->Simple_Type) { return PyUnicode_FromFormat("<%s object at %p>", @@ -4994,7 +4996,7 @@ Pointer_item(PyObject *myself, Py_ssize_t index) return NULL; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(myself))); StgInfo *stginfo; if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { return NULL; @@ -5014,7 +5016,7 @@ Pointer_item(PyObject *myself, Py_ssize_t index) size = iteminfo->size; offset = index * iteminfo->size; - return PyCData_get(proto, stginfo->getfunc, (PyObject *)self, + return PyCData_get(st, proto, stginfo->getfunc, (PyObject *)self, index, size, (*(char **)self->b_ptr) + offset); } @@ -5038,7 +5040,7 @@ Pointer_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value) return -1; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(myself))); StgInfo *stginfo; if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { return -1; @@ -5058,7 +5060,7 @@ Pointer_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value) size = iteminfo->size; offset = index * iteminfo->size; - return PyCData_set((PyObject *)self, proto, stginfo->setfunc, value, + return PyCData_set(st, (PyObject *)self, proto, stginfo->setfunc, value, index, size, (*(char **)self->b_ptr) + offset); } @@ -5071,14 +5073,14 @@ Pointer_get_contents(CDataObject *self, void *closure) return NULL; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *stginfo; if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { return NULL; } assert(stginfo); /* Cannot be NULL for pointer instances */ - return PyCData_FromBaseObj(stginfo->proto, + return PyCData_FromBaseObj(st, stginfo->proto, (PyObject *)self, 0, *(void **)self->b_ptr); } @@ -5094,7 +5096,7 @@ Pointer_set_contents(CDataObject *self, PyObject *value, void *closure) "Pointer does not support item deletion"); return -1; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *stginfo; if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { return -1; @@ -5236,7 +5238,7 @@ Pointer_subscript(PyObject *myself, PyObject *item) else len = (stop - start + 1) / step + 1; - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(myself))); StgInfo *stginfo; if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { return NULL; From 2263f820d99fe28763ceb280a8981eb26c7890ed Mon Sep 17 00:00:00 2001 From: neonene Date: Sat, 23 Mar 2024 22:57:00 +0900 Subject: [PATCH 07/38] get_module_state_by_def(Py_TYPE(type)) --- Modules/_ctypes/_ctypes.c | 80 +++++++++++++++++++++------------------ Modules/_ctypes/stgdict.c | 8 ++-- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index cc8360c177415c..4940449caea1db 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -505,7 +505,7 @@ CType_Type_sizeof(PyObject *self) Py_ssize_t size = Py_TYPE(self)->tp_basicsize; size += Py_TYPE(self)->tp_itemsize * Py_SIZE(self); - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(self)); StgInfo *info; if (PyStgInfo_FromType(st, self, &info) < 0) { return NULL; @@ -628,7 +628,7 @@ StructUnionType_init(PyObject *self, PyObject *args, PyObject *kwds, int isStruc return -1; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(self)); StgInfo *info = PyStgInfo_Init(st, (PyTypeObject *)self); if (!info) { Py_DECREF(attrdict); @@ -706,7 +706,8 @@ CDataType_from_address(PyObject *type, PyObject *value) buf = (void *)PyLong_AsVoidPtr(value); if (PyErr_Occurred()) return NULL; - return PyCData_AtAddress(type, buf); + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + return PyCData_AtAddress(st, type, buf); } PyDoc_STRVAR(from_buffer_doc, @@ -724,7 +725,7 @@ CDataType_from_buffer(PyObject *type, PyObject *args) Py_buffer *buffer; Py_ssize_t offset = 0; - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); StgInfo *info; if (PyStgInfo_FromType(st, type, &info) < 0) { return NULL; @@ -806,7 +807,7 @@ CDataType_from_buffer_copy(PyObject *type, PyObject *args) Py_ssize_t offset = 0; PyObject *result; - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); StgInfo *info; if (PyStgInfo_FromType(st, type, &info) < 0) { return NULL; @@ -908,7 +909,8 @@ CDataType_in_dll(PyObject *type, PyObject *args) return NULL; } #endif - return PyCData_AtAddress(type, address); + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + return PyCData_AtAddress(st, type, address); } PyDoc_STRVAR(from_param_doc, @@ -924,7 +926,7 @@ CDataType_from_param(PyObject *type, PyObject *value) if (res) { return Py_NewRef(value); } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); if (PyCArg_CheckExact(st, value)) { PyCArgObject *p = (PyCArgObject *)value; PyObject *ob = p->obj; @@ -981,7 +983,8 @@ CDataType_repeat(PyObject *self, Py_ssize_t length) return PyErr_Format(PyExc_ValueError, "Array length must be >= 0, not %zd", length); - return PyCArrayType_from_ctype(self, length); + ctypes_state *st = get_module_state_by_def(Py_TYPE(self)); + return PyCArrayType_from_ctype(st, self, length); } static int @@ -1158,7 +1161,7 @@ PyCPointerType_init(PyObject *self, PyObject *args, PyObject *kwds) stginfo items size, align, length contain info about pointers itself, stginfo->proto has info about the pointed to type! */ - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(self)); StgInfo *stginfo = PyStgInfo_Init(st, (PyTypeObject *)self); if (!stginfo) { return -1; @@ -1175,7 +1178,7 @@ PyCPointerType_init(PyObject *self, PyObject *args, PyObject *kwds) } if (proto) { const char *current_format; - if (-1 == PyCPointerType_SetProto(stginfo, proto)) { + if (-1 == PyCPointerType_SetProto(st, stginfo, proto)) { Py_DECREF(proto); return -1; } @@ -1216,7 +1219,7 @@ PyCPointerType_set_type(PyTypeObject *self, PyObject *type) if (!attrdict) { return NULL; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(self)); StgInfo *info; if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) { Py_DECREF(attrdict); @@ -1229,7 +1232,7 @@ PyCPointerType_set_type(PyTypeObject *self, PyObject *type) return NULL; } - if (-1 == PyCPointerType_SetProto(info, type)) { + if (-1 == PyCPointerType_SetProto(st, info, type)) { Py_DECREF(attrdict); return NULL; } @@ -1243,7 +1246,7 @@ PyCPointerType_set_type(PyTypeObject *self, PyObject *type) Py_RETURN_NONE; } -static PyObject *_byref(PyObject *); +static PyObject *_byref(ctypes_state *, PyObject *); static PyObject * PyCPointerType_from_param(PyObject *type, PyObject *value) @@ -1253,7 +1256,7 @@ PyCPointerType_from_param(PyObject *type, PyObject *value) return Py_NewRef(value); } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); StgInfo *typeinfo; if (PyStgInfo_FromType(st, type, &typeinfo) < 0) { return NULL; @@ -1271,7 +1274,7 @@ PyCPointerType_from_param(PyObject *type, PyObject *value) switch (PyObject_IsInstance(value, typeinfo->proto)) { case 1: Py_INCREF(value); /* _byref steals a refcount */ - return _byref(value); + return _byref(st, value); case -1: return NULL; default: @@ -1570,7 +1573,7 @@ PyCArrayType_init(PyObject *self, PyObject *args, PyObject *kwds) goto error; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(self)); StgInfo *stginfo = PyStgInfo_Init(st, (PyTypeObject*)self); if (!stginfo) { goto error; @@ -1683,11 +1686,12 @@ c_wchar_p_from_param(PyObject *type, PyObject *value) if (value == Py_None) { Py_RETURN_NONE; } + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); if (PyUnicode_Check(value)) { PyCArgObject *parg; struct fielddesc *fd = _ctypes_get_fielddesc("Z"); - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) return NULL; parg->pffi_type = &ffi_type_pointer; @@ -1705,7 +1709,6 @@ c_wchar_p_from_param(PyObject *type, PyObject *value) if (res) { return Py_NewRef(value); } - ctypes_state *st = GLOBAL_STATE(); if (ArrayObject_Check(st, value) || PointerObject_Check(st, value)) { /* c_wchar array instance or pointer(c_wchar(...)) */ StgInfo *it; @@ -1757,11 +1760,12 @@ c_char_p_from_param(PyObject *type, PyObject *value) if (value == Py_None) { Py_RETURN_NONE; } + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); if (PyBytes_Check(value)) { PyCArgObject *parg; struct fielddesc *fd = _ctypes_get_fielddesc("z"); - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) return NULL; parg->pffi_type = &ffi_type_pointer; @@ -1779,7 +1783,6 @@ c_char_p_from_param(PyObject *type, PyObject *value) if (res) { return Py_NewRef(value); } - ctypes_state *st = GLOBAL_STATE(); if (ArrayObject_Check(st, value) || PointerObject_Check(st, value)) { /* c_char array instance or pointer(c_char(...)) */ StgInfo *it; @@ -1833,13 +1836,15 @@ c_void_p_from_param(PyObject *type, PyObject *value) if (value == Py_None) { Py_RETURN_NONE; } + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + /* Should probably allow buffer interface as well */ /* int, long */ if (PyLong_Check(value)) { PyCArgObject *parg; struct fielddesc *fd = _ctypes_get_fielddesc("P"); - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) return NULL; parg->pffi_type = &ffi_type_pointer; @@ -1857,7 +1862,7 @@ c_void_p_from_param(PyObject *type, PyObject *value) PyCArgObject *parg; struct fielddesc *fd = _ctypes_get_fielddesc("z"); - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) return NULL; parg->pffi_type = &ffi_type_pointer; @@ -1874,7 +1879,7 @@ c_void_p_from_param(PyObject *type, PyObject *value) PyCArgObject *parg; struct fielddesc *fd = _ctypes_get_fielddesc("Z"); - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) return NULL; parg->pffi_type = &ffi_type_pointer; @@ -1894,7 +1899,6 @@ c_void_p_from_param(PyObject *type, PyObject *value) /* c_void_p instances */ return Py_NewRef(value); } - ctypes_state *st = GLOBAL_STATE(); /* ctypes array or pointer instance */ if (ArrayObject_Check(st, value) || PointerObject_Check(st, value)) { /* Any array or pointer is accepted */ @@ -1913,7 +1917,7 @@ c_void_p_from_param(PyObject *type, PyObject *value) PyCArgObject *parg; PyCFuncPtrObject *func; func = (PyCFuncPtrObject *)value; - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) return NULL; parg->pffi_type = &ffi_type_pointer; @@ -1938,7 +1942,7 @@ c_void_p_from_param(PyObject *type, PyObject *value) switch (PyUnicode_AsUTF8(stgi->proto)[0]) { case 'z': /* c_char_p */ case 'Z': /* c_wchar_p */ - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) return NULL; parg->pffi_type = &ffi_type_pointer; @@ -2107,6 +2111,7 @@ PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds) SIMPLE_TYPE_CHARS); goto error; } + ctypes_state *st = get_module_state_by_def(Py_TYPE(self)); fmt = _ctypes_get_fielddesc(proto_str); if (fmt == NULL) { PyErr_Format(PyExc_ValueError, @@ -2114,7 +2119,6 @@ PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds) goto error; } - ctypes_state *st = GLOBAL_STATE(); StgInfo *stginfo = PyStgInfo_Init(st, (PyTypeObject *)self); if (!stginfo) { goto error; @@ -2253,7 +2257,7 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value) return Py_NewRef(value); } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); StgInfo *info; if (PyStgInfo_FromType(st, type, &info) < 0) { return NULL; @@ -2271,7 +2275,7 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value) fd = _ctypes_get_fielddesc(fmt); assert(fd); - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) return NULL; @@ -2544,7 +2548,7 @@ PyCFuncPtrType_init(PyObject *self, PyObject *args, PyObject *kwds) return -1; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(self)); StgInfo *stginfo = PyStgInfo_Init(st, (PyTypeObject *)self); if (!stginfo) { Py_DECREF(attrdict); @@ -2566,7 +2570,7 @@ PyCFuncPtrType_init(PyObject *self, PyObject *args, PyObject *kwds) } stginfo->flags |= TYPEFLAG_ISPOINTER; - if (-1 == make_funcptrtype_dict(attrdict, stginfo)) { + if (-1 == make_funcptrtype_dict(st, attrdict, stginfo)) { Py_DECREF(attrdict); return -1; } @@ -3391,7 +3395,7 @@ static PPROC FindAddress(void *handle, const char *name, PyObject *type) return NULL; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); StgInfo *info; if (PyStgInfo_FromType(st, (PyObject *)type, &info) < 0) { return NULL; @@ -3641,7 +3645,8 @@ PyCFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } #endif - if (!_validate_paramflags(type, paramflags)) { + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + if (!_validate_paramflags(st, type, paramflags)) { Py_DECREF(ftuple); return NULL; } @@ -3682,7 +3687,8 @@ PyCFuncPtr_FromVtblIndex(PyTypeObject *type, PyObject *args, PyObject *kwds) if (paramflags == Py_None) paramflags = NULL; - if (!_validate_paramflags(type, paramflags)) + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + if (!_validate_paramflags(st, type, paramflags)) return NULL; self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds); @@ -3762,7 +3768,7 @@ PyCFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } */ - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); StgInfo *info; if (PyStgInfo_FromType(st, (PyObject *)type, &info) < 0) { return NULL; @@ -4354,7 +4360,7 @@ _init_pos_args(PyObject *self, PyTypeObject *type, PyObject *fields; Py_ssize_t i; - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); StgInfo *baseinfo; if (PyStgInfo_FromType(st, (PyObject *)type->tp_base, &baseinfo) < 0) { return -1; @@ -5158,7 +5164,7 @@ Pointer_init(CDataObject *self, PyObject *args, PyObject *kw) static PyObject * Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kw) { - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); StgInfo *info; if (PyStgInfo_FromType(st, (PyObject *)type, &info) < 0) { return NULL; diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index f7905b7f3fb40f..ff7e161d513fbe 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -173,7 +173,7 @@ MakeAnonFields(PyObject *type) if (anon_names == NULL) return -1; - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); PyTypeObject *cfield_tp = st->PyCField_Type; for (i = 0; i < PySequence_Fast_GET_SIZE(anon_names); ++i) { PyObject *fname = PySequence_Fast_GET_ITEM(anon_names, i); /* borrowed */ @@ -316,7 +316,7 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct return -1; } - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); StgInfo *stginfo; if (PyStgInfo_FromType(st, type, &stginfo) < 0) { return -1; @@ -488,7 +488,7 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct /* construct the field now, as `prop->offset` is `offset` with corrected alignment */ - prop = PyCField_FromDesc(desc, i, + prop = PyCField_FromDesc(st, desc, i, &field_size, bitsize, &bitofs, &size, &offset, &align, pack, big_endian); @@ -542,7 +542,7 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct size = 0; offset = 0; align = 0; - prop = PyCField_FromDesc(desc, i, + prop = PyCField_FromDesc(st, desc, i, &field_size, bitsize, &bitofs, &size, &offset, &align, pack, big_endian); From 1877767313d1f3479d9234e76c4ac000b66dbe40 Mon Sep 17 00:00:00 2001 From: neonene Date: Sat, 23 Mar 2024 23:01:03 +0900 Subject: [PATCH 08/38] split GenericPyCData_new() --- Modules/_ctypes/_ctypes.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 4940449caea1db..206fbdd73e23c1 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -797,6 +797,10 @@ CDataType_from_buffer(PyObject *type, PyObject *args) PyDoc_STRVAR(from_buffer_copy_doc, "C.from_buffer_copy(object, offset=0) -> C instance\ncreate a C instance from a readable buffer"); +static inline PyObject * +_GenericPyCData_new(ctypes_state *st, + PyTypeObject *type, PyObject *args, PyObject *kwds); + static PyObject * GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds); @@ -841,7 +845,7 @@ CDataType_from_buffer_copy(PyObject *type, PyObject *args) return NULL; } - result = GenericPyCData_new((PyTypeObject *)type, NULL, NULL); + result = _GenericPyCData_new(st, (PyTypeObject *)type, NULL, NULL); if (result != NULL) { memcpy(((CDataObject *)result)->b_ptr, (char *)buffer.buf + offset, info->size); @@ -3211,10 +3215,17 @@ PyCData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, /******************************************************************/ static PyObject * GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + return _GenericPyCData_new(st, type, args, kwds); +} + +static inline PyObject * +_GenericPyCData_new(ctypes_state *st, + PyTypeObject *type, PyObject *args, PyObject *kwds) { CDataObject *obj; - ctypes_state *st = GLOBAL_STATE(); StgInfo *info; if (PyStgInfo_FromType(st, (PyObject *)type, &info) < 0) { return NULL; @@ -3651,7 +3662,7 @@ PyCFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } - self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds); + self = (PyCFuncPtrObject *)_GenericPyCData_new(st, type, args, kwds); if (!self) { Py_DECREF(ftuple); return NULL; @@ -3691,7 +3702,7 @@ PyCFuncPtr_FromVtblIndex(PyTypeObject *type, PyObject *args, PyObject *kwds) if (!_validate_paramflags(st, type, paramflags)) return NULL; - self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds); + self = (PyCFuncPtrObject *)_GenericPyCData_new(st, type, args, kwds); self->index = index + 0x1000; self->paramflags = Py_XNewRef(paramflags); if (iid_len == sizeof(GUID)) @@ -3788,7 +3799,7 @@ PyCFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (!thunk) return NULL; - self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds); + self = (PyCFuncPtrObject *)_GenericPyCData_new(st, type, args, kwds); if (self == NULL) { Py_DECREF(thunk); return NULL; @@ -5174,7 +5185,7 @@ Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kw) "Cannot create instance: has no _type_"); return NULL; } - return GenericPyCData_new(type, args, kw); + return _GenericPyCData_new(st, type, args, kw); } static PyObject * From 6d97625a12fc4a4df6622a7a22fd51b5b223d622 Mon Sep 17 00:00:00 2001 From: neonene Date: Sat, 23 Mar 2024 23:13:26 +0900 Subject: [PATCH 09/38] move global vars to module state --- Modules/_ctypes/_ctypes.c | 34 +++++++++++++++------------------- Modules/_ctypes/callproc.c | 30 +++++++++++++++--------------- Modules/_ctypes/ctypes.h | 4 ---- 3 files changed, 30 insertions(+), 38 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 206fbdd73e23c1..fdea57eb0e9508 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1976,32 +1976,32 @@ static PyMethodDef c_void_p_method = { "from_param", c_void_p_from_param, METH_O static PyMethodDef c_char_p_method = { "from_param", c_char_p_from_param, METH_O }; static PyMethodDef c_wchar_p_method = { "from_param", c_wchar_p_from_param, METH_O }; -static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject *kwds, +static PyObject *CreateSwappedType(ctypes_state *st, PyTypeObject *type, + PyObject *args, PyObject *kwds, PyObject *proto, struct fielddesc *fmt) { PyTypeObject *result; PyObject *name = PyTuple_GET_ITEM(args, 0); PyObject *newname; PyObject *swapped_args; - static PyObject *suffix; Py_ssize_t i; swapped_args = PyTuple_New(PyTuple_GET_SIZE(args)); if (!swapped_args) return NULL; - if (suffix == NULL) + if (st->swapped_suffix == NULL) #ifdef WORDS_BIGENDIAN - suffix = PyUnicode_InternFromString("_le"); + st->swapped_suffix = PyUnicode_InternFromString("_le"); #else - suffix = PyUnicode_InternFromString("_be"); + st->swapped_suffix = PyUnicode_InternFromString("_be"); #endif - if (suffix == NULL) { + if (st->swapped_suffix == NULL) { Py_DECREF(swapped_args); return NULL; } - newname = PyUnicode_Concat(name, suffix); + newname = PyUnicode_Concat(name, st->swapped_suffix); if (newname == NULL) { Py_DECREF(swapped_args); return NULL; @@ -2021,8 +2021,6 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject if (result == NULL) return NULL; - ctypes_state *st = GLOBAL_STATE(); - StgInfo *stginfo = PyStgInfo_Init(st, result); if (!stginfo) { Py_DECREF(result); @@ -2350,7 +2348,7 @@ static PyType_Spec pycsimple_type_spec = { */ static PyObject * -converters_from_argtypes(PyObject *ob) +converters_from_argtypes(ctypes_state *st, PyObject *ob) { PyObject *converters; Py_ssize_t i; @@ -2365,7 +2363,7 @@ converters_from_argtypes(PyObject *ob) Py_ssize_t nArgs = PyTuple_GET_SIZE(ob); if (nArgs > CTYPES_MAX_ARGCOUNT) { Py_DECREF(ob); - PyErr_Format(PyExc_ArgError, + PyErr_Format(st->PyExc_ArgError, "_argtypes_ has too many arguments (%zi), maximum is %i", nArgs, CTYPES_MAX_ARGCOUNT); return NULL; @@ -4806,16 +4804,15 @@ static PyType_Spec pycarray_spec = { }; PyObject * -PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) +PyCArrayType_from_ctype(ctypes_state *st, PyObject *itemtype, Py_ssize_t length) { - static PyObject *cache; PyObject *key; char name[256]; PyObject *len; - if (cache == NULL) { - cache = PyDict_New(); - if (cache == NULL) + if (st->array_cache == NULL) { + st->array_cache = PyDict_New(); + if (st->array_cache == NULL) return NULL; } len = PyLong_FromSsize_t(length); @@ -4827,7 +4824,7 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) return NULL; PyObject *result; - if (_PyDict_GetItemProxy(cache, key, &result) != 0) { + if (_PyDict_GetItemProxy(st->array_cache, key, &result) != 0) { // found or error Py_DECREF(key); return result; @@ -4846,7 +4843,6 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) sprintf(name, "%.200s_Array_%ld", ((PyTypeObject *)itemtype)->tp_name, (long)length); #endif - ctypes_state *st = GLOBAL_STATE(); result = PyObject_CallFunction((PyObject *)st->PyCArrayType_Type, "s(O){s:n,s:O}", name, @@ -4860,7 +4856,7 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) Py_DECREF(key); return NULL; } - if (-1 == PyDict_SetItemProxy(cache, key, result)) { + if (-1 == PyDict_SetItemProxy(st, st->array_cache, key, result)) { Py_DECREF(key); Py_DECREF(result); return NULL; diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 7b5c6b59c8c769..35ba31b50dedf8 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -153,22 +153,21 @@ static void pymem_destructor(PyObject *ptr) kept alive in the thread state dictionary as long as the thread itself. */ PyObject * -_ctypes_get_errobj(int **pspace) +_ctypes_get_errobj(ctypes_state *st, int **pspace) { PyObject *dict = PyThreadState_GetDict(); PyObject *errobj; - static PyObject *error_object_name; if (dict == NULL) { PyErr_SetString(PyExc_RuntimeError, "cannot get thread state"); return NULL; } - if (error_object_name == NULL) { - error_object_name = PyUnicode_InternFromString("ctypes.error_object"); - if (error_object_name == NULL) + if (st->error_object_name == NULL) { + st->error_object_name = PyUnicode_InternFromString("ctypes.error_object"); + if (st->error_object_name == NULL) return NULL; } - if (PyDict_GetItemRef(dict, error_object_name, &errobj) < 0) { + if (PyDict_GetItemRef(dict, st->error_object_name, &errobj) < 0) { return NULL; } if (errobj) { @@ -188,7 +187,7 @@ _ctypes_get_errobj(int **pspace) PyMem_Free(space); return NULL; } - if (-1 == PyDict_SetItem(dict, error_object_name, + if (-1 == PyDict_SetItem(dict, st->error_object_name, errobj)) { Py_DECREF(errobj); return NULL; @@ -1171,7 +1170,8 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk) * * - XXX various requirements for restype, not yet collected */ -PyObject *_ctypes_callproc(PPROC pProc, +PyObject *_ctypes_callproc(ctypes_state *st, + PPROC pProc, PyObject *argtuple, #ifdef MS_WIN32 IUnknown *pIunk, @@ -1201,7 +1201,7 @@ PyObject *_ctypes_callproc(PPROC pProc, if (argcount > CTYPES_MAX_ARGCOUNT) { - PyErr_Format(PyExc_ArgError, "too many arguments (%zi), maximum is %i", + PyErr_Format(st->PyExc_ArgError, "too many arguments (%zi), maximum is %i", argcount, CTYPES_MAX_ARGCOUNT); return NULL; } @@ -1234,20 +1234,20 @@ PyObject *_ctypes_callproc(PPROC pProc, converter = PyTuple_GET_ITEM(argtypes, i); v = PyObject_CallOneArg(converter, arg); if (v == NULL) { - _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1); + _ctypes_extend_error(st->PyExc_ArgError, "argument %zd: ", i+1); goto cleanup; } - err = ConvParam(v, i+1, pa); + err = ConvParam(st, v, i+1, pa); Py_DECREF(v); if (-1 == err) { - _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1); + _ctypes_extend_error(st->PyExc_ArgError, "argument %zd: ", i+1); goto cleanup; } } else { - err = ConvParam(arg, i+1, pa); + err = ConvParam(st, arg, i+1, pa); if (-1 == err) { - _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1); + _ctypes_extend_error(st->PyExc_ArgError, "argument %zd: ", i+1); goto cleanup; /* leaking ? */ } } @@ -1256,7 +1256,7 @@ PyObject *_ctypes_callproc(PPROC pProc, if (restype == Py_None) { rtype = &ffi_type_void; } else { - rtype = _ctypes_get_ffi_type(restype); + rtype = _ctypes_get_ffi_type(st, restype); } if (!rtype) { goto cleanup; diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index b5a4fe2c3bb20e..0482e4d4ad4703 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -405,9 +405,6 @@ extern char basespec_string[]; extern ffi_type *_ctypes_get_ffi_type(PyObject *obj); -/* exception classes */ -extern PyObject *PyExc_ArgError; - extern char *_ctypes_conversion_encoding; extern char *_ctypes_conversion_errors; @@ -423,7 +420,6 @@ extern char *_ctypes_alloc_format_string_with_shape(int ndim, extern int _ctypes_simple_instance(PyObject *obj); -extern PyObject *_ctypes_ptrtype_cache; PyObject *_ctypes_get_errobj(int **pspace); #ifdef USING_MALLOC_CLOSURE_DOT_C From 6a09caddb3d832812c89abcdaff75243185f8240 Mon Sep 17 00:00:00 2001 From: neonene Date: Sat, 23 Mar 2024 23:20:01 +0900 Subject: [PATCH 10/38] prepend module state to func args --- Modules/_ctypes/_ctypes.c | 104 ++++++++++++++++-------------------- Modules/_ctypes/callbacks.c | 19 ++++--- Modules/_ctypes/callproc.c | 36 ++++++------- Modules/_ctypes/cfield.c | 3 +- Modules/_ctypes/ctypes.h | 32 ++++++----- 5 files changed, 90 insertions(+), 104 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index fdea57eb0e9508..ac1f6b0eed97e4 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -197,14 +197,13 @@ static PyType_Spec dictremover_spec = { }; int -PyDict_SetItemProxy(PyObject *dict, PyObject *key, PyObject *item) +PyDict_SetItemProxy(ctypes_state *st, PyObject *dict, PyObject *key, PyObject *item) { PyObject *obj; DictRemoverObject *remover; PyObject *proxy; int result; - ctypes_state *st = GLOBAL_STATE(); obj = _PyObject_CallNoArgs((PyObject *)st->DictRemover_Type); if (obj == NULL) return -1; @@ -553,7 +552,7 @@ static PyType_Spec pyctype_type_spec = { */ static PyCArgObject * -StructUnionType_paramfunc(CDataObject *self) +StructUnionType_paramfunc(ctypes_state *st, CDataObject *self) { PyCArgObject *parg; PyObject *obj; @@ -569,7 +568,6 @@ StructUnionType_paramfunc(CDataObject *self) /* Create a Python object which calls PyMem_Free(ptr) in its deallocator. The object will be destroyed at _ctypes_callproc() cleanup. */ - ctypes_state *st = GLOBAL_STATE(); PyTypeObject *tp = st->StructParam_Type; obj = tp->tp_alloc(tp, 0); if (obj == NULL) { @@ -585,13 +583,12 @@ StructUnionType_paramfunc(CDataObject *self) obj = Py_NewRef(self); } - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) { Py_DECREF(obj); return NULL; } - ctypes_state *st = GLOBAL_STATE(); StgInfo *stginfo; if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { Py_DECREF(obj); @@ -780,7 +777,7 @@ CDataType_from_buffer(PyObject *type, PyObject *args) return NULL; } - result = PyCData_AtAddress(type, (char *)buffer->buf + offset); + result = PyCData_AtAddress(st, type, (char *)buffer->buf + offset); if (result == NULL) { Py_DECREF(mv); return NULL; @@ -1112,9 +1109,8 @@ size property/method, and the sequence protocol. */ static int -PyCPointerType_SetProto(StgInfo *stginfo, PyObject *proto) +PyCPointerType_SetProto(ctypes_state *st, StgInfo *stginfo, PyObject *proto) { - ctypes_state *st = GLOBAL_STATE(); if (!proto || !PyType_Check(proto)) { PyErr_SetString(PyExc_TypeError, "_type_ must be a type"); @@ -1135,11 +1131,11 @@ PyCPointerType_SetProto(StgInfo *stginfo, PyObject *proto) } static PyCArgObject * -PyCPointerType_paramfunc(CDataObject *self) +PyCPointerType_paramfunc(ctypes_state *st, CDataObject *self) { PyCArgObject *parg; - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) return NULL; @@ -1512,9 +1508,9 @@ add_getset(PyTypeObject *type, PyGetSetDef *gsp) } static PyCArgObject * -PyCArrayType_paramfunc(CDataObject *self) +PyCArrayType_paramfunc(ctypes_state *st, CDataObject *self) { - PyCArgObject *p = PyCArgObject_new(); + PyCArgObject *p = PyCArgObject_new(st); if (p == NULL) return NULL; p->tag = 'P'; @@ -2040,13 +2036,12 @@ static PyObject *CreateSwappedType(ctypes_state *st, PyTypeObject *type, } static PyCArgObject * -PyCSimpleType_paramfunc(CDataObject *self) +PyCSimpleType_paramfunc(ctypes_state *st, CDataObject *self) { const char *fmt; PyCArgObject *parg; struct fielddesc *fd; - ctypes_state *st = GLOBAL_STATE(); StgInfo *info; if (PyStgInfo_FromObject(st, (PyObject *)self, &info) < 0) { return NULL; @@ -2058,7 +2053,7 @@ PyCSimpleType_paramfunc(CDataObject *self) fd = _ctypes_get_fielddesc(fmt); assert(fd); - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) return NULL; @@ -2203,7 +2198,7 @@ PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds) && fmt->setfunc_swapped && fmt->getfunc_swapped) { - PyObject *swapped = CreateSwappedType(type, args, kwds, + PyObject *swapped = CreateSwappedType(st, type, args, kwds, proto, fmt); if (swapped == NULL) { return -1; @@ -2449,7 +2444,7 @@ converters_from_argtypes(ctypes_state *st, PyObject *ob) } static int -make_funcptrtype_dict(PyObject *attrdict, StgInfo *stginfo) +make_funcptrtype_dict(ctypes_state *st, PyObject *attrdict, StgInfo *stginfo) { PyObject *ob; PyObject *converters = NULL; @@ -2478,7 +2473,7 @@ make_funcptrtype_dict(PyObject *attrdict, StgInfo *stginfo) return -1; } if (ob) { - converters = converters_from_argtypes(ob); + converters = converters_from_argtypes(st, ob); if (!converters) { Py_DECREF(ob); return -1; @@ -2492,7 +2487,6 @@ make_funcptrtype_dict(PyObject *attrdict, StgInfo *stginfo) } if (ob) { StgInfo *info; - ctypes_state *st = GLOBAL_STATE(); if (PyStgInfo_FromType(st, ob, &info) < 0) { return -1; } @@ -2527,11 +2521,11 @@ make_funcptrtype_dict(PyObject *attrdict, StgInfo *stginfo) } static PyCArgObject * -PyCFuncPtrType_paramfunc(CDataObject *self) +PyCFuncPtrType_paramfunc(ctypes_state *st, CDataObject *self) { PyCArgObject *parg; - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) return NULL; @@ -2756,9 +2750,8 @@ static PyMemberDef PyCData_members[] = { /* Find the innermost type of an array type, returning a borrowed reference */ static PyObject * -PyCData_item_type(PyObject *type) +PyCData_item_type(ctypes_state *st, PyObject *type) { - ctypes_state *st = GLOBAL_STATE(); if (PyCArrayTypeObject_Check(st, type)) { PyObject *elem_type; @@ -2770,7 +2763,7 @@ PyCData_item_type(PyObject *type) assert(stg_info); elem_type = stg_info->proto; assert(elem_type); - return PyCData_item_type(elem_type); + return PyCData_item_type(st, elem_type); } else { return type; @@ -2952,13 +2945,13 @@ PyCData_MallocBuffer(CDataObject *obj, StgInfo *info) } PyObject * -PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr) +PyCData_FromBaseObj(ctypes_state *st, + PyObject *type, PyObject *base, Py_ssize_t index, char *adr) { CDataObject *cmem; assert(PyType_Check(type)); - ctypes_state *st = GLOBAL_STATE(); StgInfo *info; if (PyStgInfo_FromType(st, type, &info) < 0) { return NULL; @@ -2974,11 +2967,11 @@ PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr) if (cmem == NULL) { return NULL; } - assert(CDataObject_Check(GLOBAL_STATE(), cmem)); + assert(CDataObject_Check(st, cmem)); cmem->b_length = info->length; cmem->b_size = info->size; if (base) { /* use base's buffer */ - assert(CDataObject_Check(GLOBAL_STATE(), base)); + assert(CDataObject_Check(st, base)); cmem->b_ptr = adr; cmem->b_needsfree = 0; cmem->b_base = (CDataObject *)Py_NewRef(base); @@ -2998,7 +2991,7 @@ PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr) Box a memory block into a CData instance. */ PyObject * -PyCData_AtAddress(PyObject *type, void *buf) +PyCData_AtAddress(ctypes_state *st, PyObject *type, void *buf) { CDataObject *pd; @@ -3008,7 +3001,6 @@ PyCData_AtAddress(PyObject *type, void *buf) assert(PyType_Check(type)); - ctypes_state *st = GLOBAL_STATE(); StgInfo *info; if (PyStgInfo_FromType(st, type, &info) < 0) { return NULL; @@ -3025,7 +3017,7 @@ PyCData_AtAddress(PyObject *type, void *buf) if (!pd) { return NULL; } - assert(CDataObject_Check(GLOBAL_STATE(), pd)); + assert(CDataObject_Check(st, pd)); pd->b_ptr = (char *)buf; pd->b_length = info->length; pd->b_size = info->size; @@ -3037,10 +3029,9 @@ PyCData_AtAddress(PyObject *type, void *buf) classes. FALSE otherwise FALSE also for subclasses of c_int and such. */ -int _ctypes_simple_instance(PyObject *obj) +int _ctypes_simple_instance(ctypes_state *st, PyObject *obj) { PyTypeObject *type = (PyTypeObject *)obj; - ctypes_state *st = GLOBAL_STATE(); if (PyCSimpleTypeObject_Check(st, type)) { return type->tp_base != st->Simple_Type; @@ -3049,27 +3040,27 @@ int _ctypes_simple_instance(PyObject *obj) } PyObject * -PyCData_get(PyObject *type, GETFUNC getfunc, PyObject *src, +PyCData_get(ctypes_state *st, PyObject *type, GETFUNC getfunc, PyObject *src, Py_ssize_t index, Py_ssize_t size, char *adr) { if (getfunc) return getfunc(adr, size); assert(type); - ctypes_state *st = GLOBAL_STATE(); StgInfo *info; if (PyStgInfo_FromType(st, type, &info) < 0) { return NULL; } - if (info && info->getfunc && !_ctypes_simple_instance(type)) + if (info && info->getfunc && !_ctypes_simple_instance(st, type)) return info->getfunc(adr, size); - return PyCData_FromBaseObj(type, src, index, adr); + return PyCData_FromBaseObj(st, type, src, index, adr); } /* Helper function for PyCData_set below. */ static PyObject * -_PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, +_PyCData_set(ctypes_state *st, + CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, Py_ssize_t size, char *ptr) { CDataObject *src; @@ -3078,7 +3069,6 @@ _PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, if (setfunc) { return setfunc(ptr, value, size); } - ctypes_state *st = GLOBAL_STATE(); if (!CDataObject_Check(st, value)) { StgInfo *info; if (PyStgInfo_FromType(st, type, &info) < 0) { @@ -3100,7 +3090,7 @@ _PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, ((PyTypeObject *)type)->tp_name); return NULL; } - result = _PyCData_set(dst, type, setfunc, ob, + result = _PyCData_set(st, dst, type, setfunc, ob, size, ptr); Py_DECREF(ob); return result; @@ -3185,12 +3175,12 @@ _PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, * to the value 'value'. */ int -PyCData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, +PyCData_set(ctypes_state *st, + PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, Py_ssize_t index, Py_ssize_t size, char *ptr) { CDataObject *mem = (CDataObject *)dst; PyObject *result; - ctypes_state *st = GLOBAL_STATE(); if (!CDataObject_Check(st, dst)) { PyErr_SetString(PyExc_TypeError, @@ -3198,7 +3188,7 @@ PyCData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, return -1; } - result = _PyCData_set(mem, type, setfunc, value, + result = _PyCData_set(st, mem, type, setfunc, value, size, ptr); if (result == NULL) return -1; @@ -3435,10 +3425,8 @@ static PPROC FindAddress(void *handle, const char *name, PyObject *type) /* Return 1 if usable, 0 else and exception set. */ static int -_check_outarg_type(PyObject *arg, Py_ssize_t index) +_check_outarg_type(ctypes_state *st, PyObject *arg, Py_ssize_t index) { - ctypes_state *st = GLOBAL_STATE(); - if (PyCPointerTypeObject_Check(st, arg)) { return 1; } @@ -3468,12 +3456,11 @@ _check_outarg_type(PyObject *arg, Py_ssize_t index) /* Returns 1 on success, 0 on error */ static int -_validate_paramflags(PyTypeObject *type, PyObject *paramflags) +_validate_paramflags(ctypes_state *st, PyTypeObject *type, PyObject *paramflags) { Py_ssize_t i, len; PyObject *argtypes; - ctypes_state *st = GLOBAL_STATE(); StgInfo *info; if (PyStgInfo_FromType(st, (PyObject *)type, &info) < 0) { return -1; @@ -3522,7 +3509,7 @@ _validate_paramflags(PyTypeObject *type, PyObject *paramflags) case PARAMFLAG_FIN | PARAMFLAG_FOUT: break; case PARAMFLAG_FOUT: - if (!_check_outarg_type(typ, i+1)) + if (!_check_outarg_type(st, typ, i+1)) return 0; break; default: @@ -3790,7 +3777,8 @@ PyCFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } - thunk = _ctypes_alloc_callback(callable, + thunk = _ctypes_alloc_callback(st, + callable, info->argtypes, info->restype, info->flags); @@ -3821,10 +3809,9 @@ PyCFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) _byref consumes a refcount to its argument */ static PyObject * -_byref(PyObject *obj) +_byref(ctypes_state *st, PyObject *obj) { PyCArgObject *parg; - ctypes_state *st = GLOBAL_STATE(); if (!CDataObject_Check(st, obj)) { PyErr_SetString(PyExc_TypeError, @@ -3832,7 +3819,7 @@ _byref(PyObject *obj) return NULL; } - parg = PyCArgObject_new(); + parg = PyCArgObject_new(st); if (parg == NULL) { Py_DECREF(obj); return NULL; @@ -3896,7 +3883,7 @@ _get_arg(int *pindex, PyObject *name, PyObject *defval, PyObject *inargs, PyObje function. */ static PyObject * -_build_callargs(PyCFuncPtrObject *self, PyObject *argtypes, +_build_callargs(ctypes_state *st, PyCFuncPtrObject *self, PyObject *argtypes, PyObject *inargs, PyObject *kwds, int *poutmask, int *pinoutmask, unsigned int *pnumretvals) { @@ -3933,7 +3920,6 @@ _build_callargs(PyCFuncPtrObject *self, PyObject *argtypes, inargs_index = 1; } #endif - ctypes_state *st = GLOBAL_STATE(); for (i = 0; i < len; ++i) { PyObject *item = PyTuple_GET_ITEM(paramflags, i); PyObject *ob; @@ -4171,7 +4157,6 @@ PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds) "native com method call without 'this' parameter"); return NULL; } - ctypes_state *st = GLOBAL_STATE(); if (!CDataObject_Check(st, this)) { PyErr_SetString(PyExc_TypeError, "Expected a COM this pointer as first argument"); @@ -4193,7 +4178,7 @@ PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds) pProc = ((void **)piunk->lpVtbl)[self->index - 0x1000]; } #endif - callargs = _build_callargs(self, argtypes, + callargs = _build_callargs(st, self, argtypes, inargs, kwds, &outmask, &inoutmask, &numretvals); if (callargs == NULL) @@ -4229,7 +4214,8 @@ PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds) } } - result = _ctypes_callproc(pProc, + result = _ctypes_callproc(st, + pProc, callargs, #ifdef MS_WIN32 piunk, diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 9fa2e18afc313e..755c8dfb928cb2 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -136,7 +136,8 @@ TryAddRef(PyObject *cnv, CDataObject *obj) * Call the python object with all arguments * */ -static void _CallPythonObject(void *mem, +static void _CallPythonObject(ctypes_state *st, + void *mem, ffi_type *restype, SETFUNC setfunc, PyObject *callable, @@ -155,7 +156,6 @@ static void _CallPythonObject(void *mem, assert(nargs <= CTYPES_MAX_ARGCOUNT); PyObject **args = alloca(nargs * sizeof(PyObject *)); PyObject **cnvs = PySequence_Fast_ITEMS(converters); - ctypes_state *st = GLOBAL_STATE(); for (i = 0; i < nargs; i++) { PyObject *cnv = cnvs[i]; // borrowed ref @@ -164,7 +164,7 @@ static void _CallPythonObject(void *mem, goto Done; } - if (info && info->getfunc && !_ctypes_simple_instance(cnv)) { + if (info && info->getfunc && !_ctypes_simple_instance(st, cnv)) { PyObject *v = info->getfunc(*pArgs, info->size); if (!v) { PrintError("create argument %zd:\n", i); @@ -205,7 +205,7 @@ static void _CallPythonObject(void *mem, } if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) { - error_object = _ctypes_get_errobj(&space); + error_object = _ctypes_get_errobj(st, &space); if (error_object == NULL) goto Done; if (flags & FUNCFLAG_USE_ERRNO) { @@ -315,12 +315,11 @@ static void closure_fcn(ffi_cif *cif, args); } -static CThunkObject* CThunkObject_new(Py_ssize_t nargs) +static CThunkObject* CThunkObject_new(ctypes_state *st, Py_ssize_t nargs) { CThunkObject *p; Py_ssize_t i; - ctypes_state *st = GLOBAL_STATE(); p = PyObject_GC_NewVar(CThunkObject, st->PyCThunk_Type, nargs); if (p == NULL) { return NULL; @@ -342,7 +341,8 @@ static CThunkObject* CThunkObject_new(Py_ssize_t nargs) return p; } -CThunkObject *_ctypes_alloc_callback(PyObject *callable, +CThunkObject *_ctypes_alloc_callback(ctypes_state *st, + PyObject *callable, PyObject *converters, PyObject *restype, int flags) @@ -354,11 +354,10 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable, assert(PyTuple_Check(converters)); nargs = PyTuple_GET_SIZE(converters); - p = CThunkObject_new(nargs); + p = CThunkObject_new(st, nargs); if (p == NULL) return NULL; - ctypes_state *st = GLOBAL_STATE(); assert(CThunk_CheckExact(st, (PyObject *)p)); p->pcl_write = Py_ffi_closure_alloc(sizeof(ffi_closure), &p->pcl_exec); @@ -371,7 +370,7 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable, PyObject **cnvs = PySequence_Fast_ITEMS(converters); for (i = 0; i < nargs; ++i) { PyObject *cnv = cnvs[i]; // borrowed ref - p->atypes[i] = _ctypes_get_ffi_type(cnv); + p->atypes[i] = _ctypes_get_ffi_type(st, cnv); } p->atypes[i] = NULL; diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 35ba31b50dedf8..69e833194073a5 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -474,10 +474,9 @@ check_hresult(PyObject *self, PyObject *args) /**************************************************************/ PyCArgObject * -PyCArgObject_new(void) +PyCArgObject_new(ctypes_state *st) { PyCArgObject *p; - ctypes_state *st = GLOBAL_STATE(); p = PyObject_GC_New(PyCArgObject, st->PyCArg_Type); if (p == NULL) return NULL; @@ -663,10 +662,10 @@ struct argument { /* * Convert a single Python object into a PyCArgObject and return it. */ -static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa) +static int ConvParam(ctypes_state *st, + PyObject *obj, Py_ssize_t index, struct argument *pa) { pa->keep = NULL; /* so we cannot forget it later */ - ctypes_state *st = GLOBAL_STATE(); StgInfo *info; int result = PyStgInfo_FromObject(st, obj, &info); @@ -678,7 +677,7 @@ static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa) PyCArgObject *carg; assert(info->paramfunc); /* If it has an stginfo, it is a CDataObject */ - carg = info->paramfunc((CDataObject *)obj); + carg = info->paramfunc(st, (CDataObject *)obj); if (carg == NULL) return -1; pa->ffi_type = carg->pffi_type; @@ -749,7 +748,7 @@ static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa) */ if (arg) { int result; - result = ConvParam(arg, index, pa); + result = ConvParam(st, arg, index, pa); Py_DECREF(arg); return result; } @@ -784,13 +783,12 @@ int can_return_struct_as_sint64(size_t s) // returns NULL with exception set on error -ffi_type *_ctypes_get_ffi_type(PyObject *obj) +ffi_type *_ctypes_get_ffi_type(ctypes_state *st, PyObject *obj) { if (obj == NULL) { return &ffi_type_sint; } - ctypes_state *st = GLOBAL_STATE(); StgInfo *info; if (PyStgInfo_FromType(st, obj, &info) < 0) { return NULL; @@ -826,7 +824,8 @@ ffi_type *_ctypes_get_ffi_type(PyObject *obj) * * void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues); */ -static int _call_function_pointer(int flags, +static int _call_function_pointer(ctypes_state *st, + int flags, PPROC pProc, void **avalues, ffi_type **atypes, @@ -927,7 +926,7 @@ static int _call_function_pointer(int flags, } if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) { - error_object = _ctypes_get_errobj(&space); + error_object = _ctypes_get_errobj(st, &space); if (error_object == NULL) return -1; } @@ -994,7 +993,8 @@ static int _call_function_pointer(int flags, * - If restype is another ctypes type, return an instance of that. * - Otherwise, call restype and return the result. */ -static PyObject *GetResult(PyObject *restype, void *result, PyObject *checker) +static PyObject *GetResult(ctypes_state *st, + PyObject *restype, void *result, PyObject *checker) { PyObject *retval, *v; @@ -1005,7 +1005,6 @@ static PyObject *GetResult(PyObject *restype, void *result, PyObject *checker) Py_RETURN_NONE; } - ctypes_state *st = GLOBAL_STATE(); StgInfo *info; if (PyStgInfo_FromType(st, restype, &info) < 0) { return NULL; @@ -1014,7 +1013,7 @@ static PyObject *GetResult(PyObject *restype, void *result, PyObject *checker) return PyObject_CallFunction(restype, "i", *(int *)result); } - if (info->getfunc && !_ctypes_simple_instance(restype)) { + if (info->getfunc && !_ctypes_simple_instance(st, restype)) { retval = info->getfunc(result, info->size); /* If restype is py_object (detected by comparing getfunc with O_get), we have to call Py_DECREF because O_get has already @@ -1024,7 +1023,7 @@ static PyObject *GetResult(PyObject *restype, void *result, PyObject *checker) Py_DECREF(retval); } } else - retval = PyCData_FromBaseObj(restype, NULL, 0, result); + retval = PyCData_FromBaseObj(st, restype, NULL, 0, result); if (!checker || !retval) return retval; @@ -1087,7 +1086,7 @@ void _ctypes_extend_error(PyObject *exc_class, const char *fmt, ...) #ifdef MS_WIN32 static PyObject * -GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk) +GetComError(ctypes_state *st, HRESULT errcode, GUID *riid, IUnknown *pIunk) { HRESULT hr; ISupportErrorInfo *psei = NULL; @@ -1139,7 +1138,6 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk) descr, source, helpfile, helpcontext, progid); if (obj) { - ctypes_state *st = GLOBAL_STATE(); PyErr_SetObject((PyObject *)st->PyComError_Type, obj); Py_DECREF(obj); } @@ -1298,7 +1296,7 @@ PyObject *_ctypes_callproc(ctypes_state *st, avalues[i] = (void *)&args[i].value; } - if (-1 == _call_function_pointer(flags, pProc, avalues, atypes, + if (-1 == _call_function_pointer(st, flags, pProc, avalues, atypes, rtype, resbuf, Py_SAFE_DOWNCAST(argcount, Py_ssize_t, int), Py_SAFE_DOWNCAST(argtype_count, Py_ssize_t, int))) @@ -1326,7 +1324,7 @@ PyObject *_ctypes_callproc(ctypes_state *st, #ifdef MS_WIN32 if (iid && pIunk) { if (*(int *)resbuf & 0x80000000) - retval = GetComError(*(HRESULT *)resbuf, iid, pIunk); + retval = GetComError(st, *(HRESULT *)resbuf, iid, pIunk); else retval = PyLong_FromLong(*(int *)resbuf); } else if (flags & FUNCFLAG_HRESULT) { @@ -1336,7 +1334,7 @@ PyObject *_ctypes_callproc(ctypes_state *st, retval = PyLong_FromLong(*(int *)resbuf); } else #endif - retval = GetResult(restype, resbuf, checker); + retval = GetResult(st, restype, resbuf, checker); cleanup: for (i = 0; i < argcount; ++i) Py_XDECREF(args[i].keep); diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 85305ca2b58b9c..2810a3a234a0c4 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -44,7 +44,7 @@ static void pymem_destructor(PyObject *ptr) * prev_desc points to the type of the previous bitfield, if any. */ PyObject * -PyCField_FromDesc(PyObject *desc, Py_ssize_t index, +PyCField_FromDesc(ctypes_state *st, PyObject *desc, Py_ssize_t index, Py_ssize_t *pfield_size, int bitsize, int *pbitofs, Py_ssize_t *psize, Py_ssize_t *poffset, Py_ssize_t *palign, int pack, int big_endian) @@ -60,7 +60,6 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index, #define CONT_BITFIELD 2 #define EXPAND_BITFIELD 3 - ctypes_state *st = GLOBAL_STATE(); PyTypeObject *tp = st->PyCField_Type; self = (CFieldObject *)tp->tp_alloc(tp, 0); if (self == NULL) diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 0482e4d4ad4703..907022bb104911 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -103,7 +103,7 @@ typedef struct tagPyCArgObject PyCArgObject; typedef struct tagCDataObject CDataObject; typedef PyObject *(* GETFUNC)(void *, Py_ssize_t size); typedef PyObject *(* SETFUNC)(void *, PyObject *value, Py_ssize_t size); -typedef PyCArgObject *(* PARAMFUNC)(CDataObject *obj); +typedef PyCArgObject *(* PARAMFUNC)(ctypes_state *st, CDataObject *obj); /* A default buffer in CDataObject, which can be used for small C types. If this buffer is too small, PyMem_Malloc will be called to create a larger one, @@ -205,13 +205,13 @@ extern struct fielddesc *_ctypes_get_fielddesc(const char *fmt); extern PyObject * -PyCField_FromDesc(PyObject *desc, Py_ssize_t index, +PyCField_FromDesc(ctypes_state *st, PyObject *desc, Py_ssize_t index, Py_ssize_t *pfield_size, int bitsize, int *pbitofs, Py_ssize_t *psize, Py_ssize_t *poffset, Py_ssize_t *palign, int pack, int is_big_endian); -extern PyObject *PyCData_AtAddress(PyObject *type, void *buf); -extern PyObject *PyCData_FromBytes(PyObject *type, char *data, Py_ssize_t length); +extern PyObject *PyCData_AtAddress(ctypes_state *st, PyObject *type, void *buf); +extern PyObject *PyCData_FromBytes(ctypes_state *st, PyObject *type, char *data, Py_ssize_t length); #define PyCArrayTypeObject_Check(st, v) PyObject_TypeCheck((v), (st)->PyCArrayType_Type) #define ArrayObject_Check(st, v) PyObject_TypeCheck((v), (st)->PyCArray_Type) @@ -222,11 +222,12 @@ extern PyObject *PyCData_FromBytes(PyObject *type, char *data, Py_ssize_t length #define PyCStructTypeObject_Check(st, v) PyObject_TypeCheck((v), (st)->PyCStructType_Type) extern PyObject * -PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length); +PyCArrayType_from_ctype(ctypes_state *st, PyObject *itemtype, Py_ssize_t length); extern PyMethodDef _ctypes_module_methods[]; -extern CThunkObject *_ctypes_alloc_callback(PyObject *callable, +extern CThunkObject *_ctypes_alloc_callback(ctypes_state *st, + PyObject *callable, PyObject *converters, PyObject *restype, int flags); @@ -336,7 +337,8 @@ extern int PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info); typedef int(* PPROC)(void); -PyObject *_ctypes_callproc(PPROC pProc, +PyObject *_ctypes_callproc(ctypes_state *st, + PPROC pProc, PyObject *arguments, #ifdef MS_WIN32 IUnknown *pIUnk, @@ -383,14 +385,15 @@ struct tagPyCArgObject { }; #define PyCArg_CheckExact(st, v) Py_IS_TYPE(v, st->PyCArg_Type) -extern PyCArgObject *PyCArgObject_new(void); +extern PyCArgObject *PyCArgObject_new(ctypes_state *st); extern PyObject * -PyCData_get(PyObject *type, GETFUNC getfunc, PyObject *src, +PyCData_get(ctypes_state *st, PyObject *type, GETFUNC getfunc, PyObject *src, Py_ssize_t index, Py_ssize_t size, char *ptr); extern int -PyCData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, +PyCData_set(ctypes_state *st, + PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, Py_ssize_t index, Py_ssize_t size, char *ptr); extern void _ctypes_extend_error(PyObject *exc_class, const char *fmt, ...); @@ -403,7 +406,7 @@ struct basespec { extern char basespec_string[]; -extern ffi_type *_ctypes_get_ffi_type(PyObject *obj); +extern ffi_type *_ctypes_get_ffi_type(ctypes_state *st, PyObject *obj); extern char *_ctypes_conversion_encoding; extern char *_ctypes_conversion_errors; @@ -412,15 +415,16 @@ extern char *_ctypes_conversion_errors; extern void _ctypes_free_closure(void *); extern void *_ctypes_alloc_closure(void); -extern PyObject *PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr); +extern PyObject *PyCData_FromBaseObj(ctypes_state *st, PyObject *type, + PyObject *base, Py_ssize_t index, char *adr); extern char *_ctypes_alloc_format_string(const char *prefix, const char *suffix); extern char *_ctypes_alloc_format_string_with_shape(int ndim, const Py_ssize_t *shape, const char *prefix, const char *suffix); -extern int _ctypes_simple_instance(PyObject *obj); +extern int _ctypes_simple_instance(ctypes_state *st, PyObject *obj); -PyObject *_ctypes_get_errobj(int **pspace); +PyObject *_ctypes_get_errobj(ctypes_state *st, int **pspace); #ifdef USING_MALLOC_CLOSURE_DOT_C void Py_ffi_closure_free(void *p); From c24df4dbab9fdb955f041b0db0dab037caf2566f Mon Sep 17 00:00:00 2001 From: neonene Date: Sun, 24 Mar 2024 00:18:16 +0900 Subject: [PATCH 11/38] fix typos --- Modules/_ctypes/_ctypes.c | 2 +- Modules/_ctypes/ctypes.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index ac1f6b0eed97e4..2bd7932228aecb 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -796,7 +796,7 @@ PyDoc_STRVAR(from_buffer_copy_doc, static inline PyObject * _GenericPyCData_new(ctypes_state *st, - PyTypeObject *type, PyObject *args, PyObject *kwds); + PyTypeObject *type, PyObject *args, PyObject *kwds); static PyObject * GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds); diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 907022bb104911..76e52ac02fe7b3 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -74,7 +74,7 @@ typedef struct { } ctypes_state; -extern PyModuleDef _ctypesmodule; +extern struct PyModuleDef _ctypesmodule; static inline ctypes_state * From 678ffa0992b04e1c0cf09335469b015322b1b014 Mon Sep 17 00:00:00 2001 From: neonene Date: Sun, 24 Mar 2024 00:41:08 +0900 Subject: [PATCH 12/38] ignored.tsv --- Tools/c-analyzer/cpython/ignored.tsv | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index 965346b9b04a32..e0ae39036c128d 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -198,6 +198,7 @@ Python/pystate.c - _Py_tss_tstate - Include/internal/pycore_blocks_output_buffer.h - BUFFER_BLOCK_SIZE - Modules/_csv.c - quote_styles - +Modules/_ctypes/_ctypes.c - _ctypesmodule - Modules/_ctypes/cfield.c - ffi_type_double - Modules/_ctypes/cfield.c - ffi_type_float - Modules/_ctypes/cfield.c - ffi_type_longdouble - From 83ec01849fd9db9c94001f5b8ef09d74ac46471f Mon Sep 17 00:00:00 2001 From: neonene Date: Sun, 24 Mar 2024 03:22:25 +0900 Subject: [PATCH 13/38] _PyType_GetModuleState() with assert --- Modules/_ctypes/callbacks.c | 2 +- Modules/_ctypes/cfield.c | 4 ++-- Modules/_ctypes/ctypes.h | 8 ++++++++ Modules/_ctypes/stgdict.c | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 755c8dfb928cb2..7b0d0a354dbfb7 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -303,7 +303,7 @@ static void closure_fcn(ffi_cif *cif, void *userdata) { CThunkObject *p = (CThunkObject *)userdata; - ctypes_state *st = _PyType_GetModuleState(Py_TYPE(p)); + ctypes_state *st = get_module_state_by_cls(Py_TYPE(p)); _CallPythonObject(st, resp, diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 2810a3a234a0c4..986dc414690425 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -216,7 +216,7 @@ PyCField_set(CFieldObject *self, PyObject *inst, PyObject *value) { CDataObject *dst; char *ptr; - ctypes_state *st = _PyType_GetModuleState(Py_TYPE(self)); + ctypes_state *st = get_module_state_by_cls(Py_TYPE(self)); if (!CDataObject_Check(st, inst)) { PyErr_SetString(PyExc_TypeError, "not a ctype instance"); @@ -240,7 +240,7 @@ PyCField_get(CFieldObject *self, PyObject *inst, PyTypeObject *type) if (inst == NULL) { return Py_NewRef(self); } - ctypes_state *st = _PyType_GetModuleState(Py_TYPE(self)); + ctypes_state *st = get_module_state_by_cls(Py_TYPE(self)); if (!CDataObject_Check(st, inst)) { PyErr_SetString(PyExc_TypeError, "not a ctype instance"); diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 76e52ac02fe7b3..029e51263f2bc7 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -84,6 +84,14 @@ get_module_state(PyObject *module) { return (ctypes_state *)state; } +static inline ctypes_state * +get_module_state_by_cls(PyTypeObject *cls) +{ + ctypes_state *state = (ctypes_state *)_PyType_GetModuleState(cls); + assert(state != NULL); + return state; +} + static inline ctypes_state * get_module_state_by_def(PyTypeObject *cls) { diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index ff7e161d513fbe..28f2f72f48a421 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -92,7 +92,7 @@ MakeFields(PyObject *type, CFieldObject *descr, if (fieldlist == NULL) return -1; - ctypes_state *st = _PyType_GetModuleState(Py_TYPE(descr)); + ctypes_state *st = get_module_state_by_cls(Py_TYPE(descr)); PyTypeObject *cfield_tp = st->PyCField_Type; for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) { PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */ From 012f8b88f248eace0135bc213c13f2207c107066 Mon Sep 17 00:00:00 2001 From: neonene Date: Sun, 24 Mar 2024 04:29:49 +0900 Subject: [PATCH 14/38] get_module_state_by_cls -> _by_class --- Modules/_ctypes/callbacks.c | 2 +- Modules/_ctypes/cfield.c | 4 ++-- Modules/_ctypes/ctypes.h | 2 +- Modules/_ctypes/stgdict.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 7b0d0a354dbfb7..9fedeab43f866e 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -303,7 +303,7 @@ static void closure_fcn(ffi_cif *cif, void *userdata) { CThunkObject *p = (CThunkObject *)userdata; - ctypes_state *st = get_module_state_by_cls(Py_TYPE(p)); + ctypes_state *st = get_module_state_by_class(Py_TYPE(p)); _CallPythonObject(st, resp, diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 986dc414690425..7472a4c36868a8 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -216,7 +216,7 @@ PyCField_set(CFieldObject *self, PyObject *inst, PyObject *value) { CDataObject *dst; char *ptr; - ctypes_state *st = get_module_state_by_cls(Py_TYPE(self)); + ctypes_state *st = get_module_state_by_class(Py_TYPE(self)); if (!CDataObject_Check(st, inst)) { PyErr_SetString(PyExc_TypeError, "not a ctype instance"); @@ -240,7 +240,7 @@ PyCField_get(CFieldObject *self, PyObject *inst, PyTypeObject *type) if (inst == NULL) { return Py_NewRef(self); } - ctypes_state *st = get_module_state_by_cls(Py_TYPE(self)); + ctypes_state *st = get_module_state_by_class(Py_TYPE(self)); if (!CDataObject_Check(st, inst)) { PyErr_SetString(PyExc_TypeError, "not a ctype instance"); diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 029e51263f2bc7..9b77372932fb73 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -85,7 +85,7 @@ get_module_state(PyObject *module) { } static inline ctypes_state * -get_module_state_by_cls(PyTypeObject *cls) +get_module_state_by_class(PyTypeObject *cls) { ctypes_state *state = (ctypes_state *)_PyType_GetModuleState(cls); assert(state != NULL); diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 28f2f72f48a421..d4884ffa2fa67e 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -92,7 +92,7 @@ MakeFields(PyObject *type, CFieldObject *descr, if (fieldlist == NULL) return -1; - ctypes_state *st = get_module_state_by_cls(Py_TYPE(descr)); + ctypes_state *st = get_module_state_by_class(Py_TYPE(descr)); PyTypeObject *cfield_tp = st->PyCField_Type; for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) { PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */ From 28696c2e33ed1e690d2c29ed436b45603b434389 Mon Sep 17 00:00:00 2001 From: neonene Date: Thu, 28 Mar 2024 22:41:47 +0900 Subject: [PATCH 15/38] assert(module) in create_pointer_type() --- Modules/_ctypes/callproc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 69e833194073a5..fb5784233c0bca 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -1954,6 +1954,7 @@ create_pointer_type(PyObject *module, PyObject *cls) PyTypeObject *typ; PyObject *key; + assert(module); ctypes_state *st = get_module_state(module); if (PyDict_GetItemRef(st->_ctypes_ptrtype_cache, cls, &result) != 0) { // found or error From a228d3537accab1ea6c7cf953066e9fd84ae30b5 Mon Sep 17 00:00:00 2001 From: neonene Date: Fri, 29 Mar 2024 16:01:25 +0900 Subject: [PATCH 16/38] sync styles with #117189 --- Modules/_ctypes/_ctypes.c | 42 +++++++++++++++++++++----------------- Modules/_ctypes/callproc.c | 20 ++++++++++-------- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 2bd7932228aecb..55337546fe4e8a 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -795,7 +795,7 @@ PyDoc_STRVAR(from_buffer_copy_doc, "C.from_buffer_copy(object, offset=0) -> C instance\ncreate a C instance from a readable buffer"); static inline PyObject * -_GenericPyCData_new(ctypes_state *st, +generic_pycdata_new(ctypes_state *st, PyTypeObject *type, PyObject *args, PyObject *kwds); static PyObject * @@ -842,7 +842,7 @@ CDataType_from_buffer_copy(PyObject *type, PyObject *args) return NULL; } - result = _GenericPyCData_new(st, (PyTypeObject *)type, NULL, NULL); + result = generic_pycdata_new(st, (PyTypeObject *)type, NULL, NULL); if (result != NULL) { memcpy(((CDataObject *)result)->b_ptr, (char *)buffer.buf + offset, info->size); @@ -1178,7 +1178,7 @@ PyCPointerType_init(PyObject *self, PyObject *args, PyObject *kwds) } if (proto) { const char *current_format; - if (-1 == PyCPointerType_SetProto(st, stginfo, proto)) { + if (PyCPointerType_SetProto(st, stginfo, proto) < 0) { Py_DECREF(proto); return -1; } @@ -1232,7 +1232,7 @@ PyCPointerType_set_type(PyTypeObject *self, PyObject *type) return NULL; } - if (-1 == PyCPointerType_SetProto(st, info, type)) { + if (PyCPointerType_SetProto(st, info, type) < 0) { Py_DECREF(attrdict); return NULL; } @@ -1986,12 +1986,13 @@ static PyObject *CreateSwappedType(ctypes_state *st, PyTypeObject *type, if (!swapped_args) return NULL; - if (st->swapped_suffix == NULL) + if (st->swapped_suffix == NULL) { #ifdef WORDS_BIGENDIAN st->swapped_suffix = PyUnicode_InternFromString("_le"); #else st->swapped_suffix = PyUnicode_InternFromString("_be"); #endif + } if (st->swapped_suffix == NULL) { Py_DECREF(swapped_args); return NULL; @@ -2108,7 +2109,6 @@ PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds) SIMPLE_TYPE_CHARS); goto error; } - ctypes_state *st = get_module_state_by_def(Py_TYPE(self)); fmt = _ctypes_get_fielddesc(proto_str); if (fmt == NULL) { PyErr_Format(PyExc_ValueError, @@ -2116,6 +2116,7 @@ PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds) goto error; } + ctypes_state *st = get_module_state_by_def(Py_TYPE(self)); StgInfo *stginfo = PyStgInfo_Init(st, (PyTypeObject *)self); if (!stginfo) { goto error; @@ -2566,7 +2567,7 @@ PyCFuncPtrType_init(PyObject *self, PyObject *args, PyObject *kwds) } stginfo->flags |= TYPEFLAG_ISPOINTER; - if (-1 == make_funcptrtype_dict(st, attrdict, stginfo)) { + if (make_funcptrtype_dict(st, attrdict, stginfo) < 0) { Py_DECREF(attrdict); return -1; } @@ -3050,8 +3051,9 @@ PyCData_get(ctypes_state *st, PyObject *type, GETFUNC getfunc, PyObject *src, if (PyStgInfo_FromType(st, type, &info) < 0) { return NULL; } - if (info && info->getfunc && !_ctypes_simple_instance(st, type)) + if (info && info->getfunc && !_ctypes_simple_instance(st, type)) { return info->getfunc(adr, size); + } return PyCData_FromBaseObj(st, type, src, index, adr); } @@ -3205,11 +3207,11 @@ static PyObject * GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); - return _GenericPyCData_new(st, type, args, kwds); + return generic_pycdata_new(st, type, args, kwds); } static inline PyObject * -_GenericPyCData_new(ctypes_state *st, +generic_pycdata_new(ctypes_state *st, PyTypeObject *type, PyObject *args, PyObject *kwds) { CDataObject *obj; @@ -3647,7 +3649,7 @@ PyCFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } - self = (PyCFuncPtrObject *)_GenericPyCData_new(st, type, args, kwds); + self = (PyCFuncPtrObject *)generic_pycdata_new(st, type, args, kwds); if (!self) { Py_DECREF(ftuple); return NULL; @@ -3684,10 +3686,10 @@ PyCFuncPtr_FromVtblIndex(PyTypeObject *type, PyObject *args, PyObject *kwds) paramflags = NULL; ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); - if (!_validate_paramflags(st, type, paramflags)) + if (!_validate_paramflags(st, type, paramflags)) { return NULL; - - self = (PyCFuncPtrObject *)_GenericPyCData_new(st, type, args, kwds); + } + self = (PyCFuncPtrObject *)generic_pycdata_new(st, type, args, kwds); self->index = index + 0x1000; self->paramflags = Py_XNewRef(paramflags); if (iid_len == sizeof(GUID)) @@ -3785,7 +3787,7 @@ PyCFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (!thunk) return NULL; - self = (PyCFuncPtrObject *)_GenericPyCData_new(st, type, args, kwds); + self = (PyCFuncPtrObject *)generic_pycdata_new(st, type, args, kwds); if (self == NULL) { Py_DECREF(thunk); return NULL; @@ -4798,8 +4800,9 @@ PyCArrayType_from_ctype(ctypes_state *st, PyObject *itemtype, Py_ssize_t length) if (st->array_cache == NULL) { st->array_cache = PyDict_New(); - if (st->array_cache == NULL) + if (st->array_cache == NULL) { return NULL; + } } len = PyLong_FromSsize_t(length); if (len == NULL) @@ -4842,7 +4845,7 @@ PyCArrayType_from_ctype(ctypes_state *st, PyObject *itemtype, Py_ssize_t length) Py_DECREF(key); return NULL; } - if (-1 == PyDict_SetItemProxy(st, st->array_cache, key, result)) { + if (PyDict_SetItemProxy(st, st->array_cache, key, result) < 0) { Py_DECREF(key); Py_DECREF(result); return NULL; @@ -5167,7 +5170,7 @@ Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kw) "Cannot create instance: has no _type_"); return NULL; } - return _GenericPyCData_new(st, type, args, kw); + return generic_pycdata_new(st, type, args, kw); } static PyObject * @@ -5475,8 +5478,9 @@ cast(void *ptr, PyObject *src, PyObject *ctype) ctypes_state *st = get_module_state(mod); CDataObject *result; - if (0 == cast_check_pointertype(st, ctype)) + if (cast_check_pointertype(st, ctype) == 0) { return NULL; + } result = (CDataObject *)_PyObject_CallNoArgs(ctype); if (result == NULL) return NULL; diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index fb5784233c0bca..1310df97e0740c 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -164,8 +164,9 @@ _ctypes_get_errobj(ctypes_state *st, int **pspace) } if (st->error_object_name == NULL) { st->error_object_name = PyUnicode_InternFromString("ctypes.error_object"); - if (st->error_object_name == NULL) + if (st->error_object_name == NULL) { return NULL; + } } if (PyDict_GetItemRef(dict, st->error_object_name, &errobj) < 0) { return NULL; @@ -187,8 +188,7 @@ _ctypes_get_errobj(ctypes_state *st, int **pspace) PyMem_Free(space); return NULL; } - if (-1 == PyDict_SetItem(dict, st->error_object_name, - errobj)) { + if (PyDict_SetItem(dict, st->error_object_name, errobj) < 0) { Py_DECREF(errobj); return NULL; } @@ -1022,9 +1022,10 @@ static PyObject *GetResult(ctypes_state *st, if (info->getfunc == _ctypes_get_fielddesc("O")->getfunc) { Py_DECREF(retval); } - } else + } + else { retval = PyCData_FromBaseObj(st, restype, NULL, 0, result); - + } if (!checker || !retval) return retval; @@ -1464,8 +1465,9 @@ copy_com_pointer(PyObject *self, PyObject *args) a.keep = b.keep = NULL; ctypes_state *st = get_module_state(self); - if (-1 == ConvParam(st, p1, 0, &a) || -1 == ConvParam(st, p2, 1, &b)) + if (ConvParam(st, p1, 0, &a) < 0 || ConvParam(st, p2, 1, &b) < 0) { goto done; + } src = (IUnknown *)a.value.p; pdst = (IUnknown **)b.value.p; @@ -1645,7 +1647,7 @@ call_function(PyObject *self, PyObject *args) } ctypes_state *st = get_module_state(self); - result = _ctypes_callproc(st, + result = _ctypes_callproc(st, (PPROC)func, arguments, #ifdef MS_WIN32 @@ -1682,7 +1684,7 @@ call_cdeclfunction(PyObject *self, PyObject *args) } ctypes_state *st = get_module_state(self); - result = _ctypes_callproc(st, + result = _ctypes_callproc(st, (PPROC)func, arguments, #ifdef MS_WIN32 @@ -1989,7 +1991,7 @@ create_pointer_type(PyObject *module, PyObject *cls) PyErr_SetString(PyExc_TypeError, "must be a ctypes type"); return NULL; } - if (-1 == PyDict_SetItem(st->_ctypes_ptrtype_cache, key, result)) { + if (PyDict_SetItem(st->_ctypes_ptrtype_cache, key, result) < 0) { Py_DECREF(result); Py_DECREF(key); return NULL; From de5110f3e4abfa506622e4132f70e7c43c7ec288 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 29 Mar 2024 12:21:41 +0000 Subject: [PATCH 17/38] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst diff --git a/Misc/NEWS.d/next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst b/Misc/NEWS.d/next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst new file mode 100644 index 00000000000000..466e1058bd282d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst @@ -0,0 +1 @@ +Isolate :mod:`!_ctypes` (apply :pep:`687`). From 4d69bdc3822957d29009a6b421af92c3a33e2920 Mon Sep 17 00:00:00 2001 From: neonene Date: Sat, 30 Mar 2024 09:47:14 +0900 Subject: [PATCH 18/38] PyType_GetModuleByDef() for fini --- Modules/_ctypes/_ctypes.c | 26 ++++++++++---------------- Modules/_ctypes/ctypes.h | 16 ++++++++++++++-- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 55337546fe4e8a..0e15611c0650cd 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -457,13 +457,11 @@ _ctype_clear_stginfo(StgInfo *info) static int CType_Type_clear(PyObject *self) { - PyTypeObject *type = Py_TYPE(self); - ctypes_state *st = type->tp_mro ? get_module_state_by_def(type) : NULL; - + ctypes_state *st = get_module_state_by_def_final(Py_TYPE(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); @@ -475,8 +473,7 @@ CType_Type_clear(PyObject *self) static void CType_Type_dealloc(PyObject *self) { - PyTypeObject *type = Py_TYPE(self); - ctypes_state *st = type->tp_mro ? get_module_state_by_def(type) : NULL; + ctypes_state *st = get_module_state_by_def_final(Py_TYPE(self)); if (st && st->PyCType_Type) { StgInfo *info; @@ -494,8 +491,9 @@ CType_Type_dealloc(PyObject *self) } } + PyTypeObject *tp = Py_TYPE(self); PyType_Type.tp_dealloc(self); - Py_DECREF(type); + Py_DECREF(tp); } static PyObject * @@ -991,13 +989,11 @@ CDataType_repeat(PyObject *self, Py_ssize_t length) static int CDataType_clear(PyTypeObject *self) { - PyTypeObject *type = Py_TYPE(self); - ctypes_state *st = type->tp_mro ? get_module_state_by_def(type) : NULL; - + ctypes_state *st = get_module_state_by_def_final(Py_TYPE(self)); if (st && st->PyCType_Type) { StgInfo *info; if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) { - return -1; + PyErr_WriteUnraisable(self); } if (info) { Py_CLEAR(info->proto); @@ -1009,19 +1005,17 @@ CDataType_clear(PyTypeObject *self) static int CDataType_traverse(PyTypeObject *self, visitproc visit, void *arg) { - PyTypeObject *type = Py_TYPE(self); - ctypes_state *st = type->tp_mro ? get_module_state_by_def(type) : NULL; - + ctypes_state *st = get_module_state_by_def_final(Py_TYPE(self)); if (st && st->PyCType_Type) { StgInfo *info; if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) { - return -1; + PyErr_WriteUnraisable(self); } if (info) { Py_VISIT(info->proto); } } - Py_VISIT(type); + Py_VISIT(Py_TYPE(self)); return PyType_Type.tp_traverse((PyObject *)self, visit, arg); } diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 9b77372932fb73..6b35de49e6771d 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -95,13 +95,25 @@ get_module_state_by_class(PyTypeObject *cls) static inline ctypes_state * get_module_state_by_def(PyTypeObject *cls) { - // NOTE: class's tp_mro slot can be cleared by the GC during a module - // finalization, which PyType_GetModuleByDef() does not expect. PyObject *mod = PyType_GetModuleByDef(cls, &_ctypesmodule); assert(mod != NULL); return get_module_state(mod); } +static inline ctypes_state * +get_module_state_by_def_final(PyTypeObject *cls) +{ + if (cls->tp_mro == NULL) { + return NULL; + } + PyObject *mod = PyType_GetModuleByDef(cls, &_ctypesmodule); + if (mod == NULL) { + PyErr_Clear(); + return NULL; + } + return get_module_state(mod); +} + extern PyType_Spec carg_spec; extern PyType_Spec cfield_spec; From f2655eb812bea4303b19cf93e59d416568f0f974 Mon Sep 17 00:00:00 2001 From: neonene Date: Sat, 30 Mar 2024 09:54:01 +0900 Subject: [PATCH 19/38] fix warning --- Modules/_ctypes/_ctypes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 0e15611c0650cd..509ac33f37db1e 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -993,7 +993,7 @@ CDataType_clear(PyTypeObject *self) if (st && st->PyCType_Type) { StgInfo *info; if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) { - PyErr_WriteUnraisable(self); + PyErr_WriteUnraisable((PyObject *)self); } if (info) { Py_CLEAR(info->proto); @@ -1009,7 +1009,7 @@ CDataType_traverse(PyTypeObject *self, visitproc visit, void *arg) if (st && st->PyCType_Type) { StgInfo *info; if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) { - PyErr_WriteUnraisable(self); + PyErr_WriteUnraisable((PyObject *)self); } if (info) { Py_VISIT(info->proto); From b5932ca821e1f519400e75c4758818b6ecf330a8 Mon Sep 17 00:00:00 2001 From: neonene Date: Tue, 2 Apr 2024 20:26:00 +0900 Subject: [PATCH 20/38] correct merge confict resolution --- Modules/_ctypes/_ctypes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 32d15d4aff74c6..087c815718b119 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -439,7 +439,7 @@ static PyType_Spec structparam_spec = { static int CType_Type_traverse(PyObject *self, visitproc visit, void *arg) { - ctypes_state *st = GLOBAL_STATE(); + ctypes_state *st = get_module_state_by_def_final(Py_TYPE(self)); if (st && st->PyCType_Type) { StgInfo *info; if (PyStgInfo_FromType(st, self, &info) < 0) { @@ -1008,6 +1008,7 @@ CType_Type_repeat(PyObject *self, Py_ssize_t length) return PyCArrayType_from_ctype(st, self, length); } + static int PyCStructType_setattro(PyObject *self, PyObject *key, PyObject *value) { From 737f29eb64439377fb01034ee3209de69ad11dee Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 2 Apr 2024 15:45:06 +0200 Subject: [PATCH 21/38] Use Argument Clinic and the defining_class for __sizeof__ --- Modules/_ctypes/_ctypes.c | 27 +++++++++++++++++++++++---- Modules/_ctypes/clinic/_ctypes.c.h | 26 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 Modules/_ctypes/clinic/_ctypes.c.h diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 087c815718b119..93524f0e1cc49a 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -126,6 +126,12 @@ bytes(cdata) #include "pycore_long.h" // _PyLong_GetZero() +/*[clinic input] +module _ctypes +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=476a19c49b31a75c]*/ +#include "clinic/_ctypes.c.h" + /****************************************************************/ @@ -436,6 +442,11 @@ static PyType_Spec structparam_spec = { CType_Type - a base metaclass. Its instances (classes) have a StgInfo. */ +/*[clinic input] +class _ctypes.CType_Type "PyObject *" "st->CType_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f385b8663b8be200]*/ + static int CType_Type_traverse(PyObject *self, visitproc visit, void *arg) { @@ -512,13 +523,22 @@ CType_Type_dealloc(PyObject *self) Py_DECREF(tp); } +/*[clinic input] +_ctypes.CType_Type.__sizeof__ + + cls: defining_class + +Return memory consumption of the type object. +[clinic start generated code]*/ + static PyObject * -CType_Type_sizeof(PyObject *self) +_ctypes_CType_Type___sizeof___impl(PyObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=c68c235be84d03f3 input=15b579e4b5aaeea2]*/ { Py_ssize_t size = Py_TYPE(self)->tp_basicsize; size += Py_TYPE(self)->tp_itemsize * Py_SIZE(self); - ctypes_state *st = get_module_state_by_def(Py_TYPE(self)); + ctypes_state *st = get_module_state_by_class(cls); StgInfo *info; if (PyStgInfo_FromType(st, self, &info) < 0) { return NULL; @@ -541,8 +561,7 @@ 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.")}, + _CTYPES_CTYPE_TYPE___SIZEOF___METHODDEF {0}, }; diff --git a/Modules/_ctypes/clinic/_ctypes.c.h b/Modules/_ctypes/clinic/_ctypes.c.h new file mode 100644 index 00000000000000..b5d5d700b12a28 --- /dev/null +++ b/Modules/_ctypes/clinic/_ctypes.c.h @@ -0,0 +1,26 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_ctypes_CType_Type___sizeof____doc__, +"__sizeof__($self, /)\n" +"--\n" +"\n" +"Return memory consumption of the type object."); + +#define _CTYPES_CTYPE_TYPE___SIZEOF___METHODDEF \ + {"__sizeof__", _PyCFunction_CAST(_ctypes_CType_Type___sizeof__), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _ctypes_CType_Type___sizeof____doc__}, + +static PyObject * +_ctypes_CType_Type___sizeof___impl(PyObject *self, PyTypeObject *cls); + +static PyObject * +_ctypes_CType_Type___sizeof__(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) { + PyErr_SetString(PyExc_TypeError, "__sizeof__() takes no arguments"); + return NULL; + } + return _ctypes_CType_Type___sizeof___impl(self, cls); +} +/*[clinic end generated code: output=beb4e4935b16dab4 input=a9049054013a1b77]*/ From 96bebd0576bdd330a0abc3d2add56285f124a689 Mon Sep 17 00:00:00 2001 From: neonene Date: Wed, 3 Apr 2024 13:30:43 +0900 Subject: [PATCH 22/38] edit blank --- Modules/_ctypes/_ctypes.c | 2 -- Modules/_ctypes/ctypes.h | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 087c815718b119..7f995b4d3c2bf9 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -490,7 +490,6 @@ static void CType_Type_dealloc(PyObject *self) { ctypes_state *st = get_module_state_by_def_final(Py_TYPE(self)); - if (st && st->PyCType_Type) { StgInfo *info; if (PyStgInfo_FromType(st, self, &info) < 0) { @@ -506,7 +505,6 @@ CType_Type_dealloc(PyObject *self) ctype_clear_stginfo(info); } } - PyTypeObject *tp = Py_TYPE(self); PyType_Type.tp_dealloc(self); Py_DECREF(tp); diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 7850e4d64c54fa..20c68134be2804 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -78,7 +78,8 @@ extern struct PyModuleDef _ctypesmodule; static inline ctypes_state * -get_module_state(PyObject *module) { +get_module_state(PyObject *module) +{ void *state = _PyModule_GetState(module); assert(state != NULL); return (ctypes_state *)state; From 5d7ac4bcfdc08ff81d48e6058c079fcf5d189787 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 4 Apr 2024 11:49:01 +0900 Subject: [PATCH 23/38] AC1: module, class, special cases --- Modules/_ctypes/_ctypes.c | 74 +++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 7f995b4d3c2bf9..01557df221ac6c 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -126,6 +126,20 @@ bytes(cdata) #include "pycore_long.h" // _PyLong_GetZero() +/*[clinic input] +module _ctypes +class _ctypes.CDataType "PyObject *" "" +class _ctypes.PyCPointerType "PyObject *" "PyCPointerType_Type" +class _ctypes.PyCSimpleType "PyObject *" "PyCSimpleType_Type" +class _ctypes.PyCData "PyObject *" "PyCData_Type" +class _ctypes.Simple "PyObject *" "Simple_Type" +class _ctypes.c_char_p "PyObject *" "" +class _ctypes.c_wchar_p "PyObject *" "" +class _ctypes.c_void_p "PyObject *" "" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=93e86f795c9444ba]*/ + +#include "clinic/_ctypes.c.h" /****************************************************************/ @@ -1640,15 +1654,25 @@ _type_ attribute. static const char SIMPLE_TYPE_CHARS[] = "cbBhHiIlLdfuzZqQPXOv?g"; +/*[clinic input] +_ctypes.c_wchar_p.from_param as c_wchar_p_from_param + + type: self + cls: defining_class + value: object + / +[clinic start generated code]*/ + static PyObject * -c_wchar_p_from_param(PyObject *type, PyObject *value) +c_wchar_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value) +/*[clinic end generated code: output=e453949a2f725a4c input=d322c7237a319607]*/ { PyObject *as_parameter; int res; if (value == Py_None) { Py_RETURN_NONE; } - ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + ctypes_state *st = get_module_state_by_class(cls->tp_base); if (PyUnicode_Check(value)) { PyCArgObject *parg; struct fielddesc *fd = _ctypes_get_fielddesc("Z"); @@ -1704,7 +1728,7 @@ c_wchar_p_from_param(PyObject *type, PyObject *value) return NULL; } if (as_parameter) { - value = c_wchar_p_from_param(type, as_parameter); + value = c_wchar_p_from_param_impl(type, cls, as_parameter); Py_DECREF(as_parameter); return value; } @@ -1714,15 +1738,25 @@ c_wchar_p_from_param(PyObject *type, PyObject *value) return NULL; } +/*[clinic input] +_ctypes.c_char_p.from_param as c_char_p_from_param + + type: self + cls: defining_class + value: object + / +[clinic start generated code]*/ + static PyObject * -c_char_p_from_param(PyObject *type, PyObject *value) +c_char_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value) +/*[clinic end generated code: output=219652ab7c174aa1 input=6cf0d1b6bb4ede11]*/ { PyObject *as_parameter; int res; if (value == Py_None) { Py_RETURN_NONE; } - ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + ctypes_state *st = get_module_state_by_class(cls->tp_base); if (PyBytes_Check(value)) { PyCArgObject *parg; struct fielddesc *fd = _ctypes_get_fielddesc("z"); @@ -1778,7 +1812,7 @@ c_char_p_from_param(PyObject *type, PyObject *value) return NULL; } if (as_parameter) { - value = c_char_p_from_param(type, as_parameter); + value = c_char_p_from_param_impl(type, cls, as_parameter); Py_DECREF(as_parameter); return value; } @@ -1788,8 +1822,18 @@ c_char_p_from_param(PyObject *type, PyObject *value) return NULL; } +/*[clinic input] +_ctypes.c_void_p.from_param as c_void_p_from_param + + type: self + cls: defining_class + value: object + / +[clinic start generated code]*/ + static PyObject * -c_void_p_from_param(PyObject *type, PyObject *value) +c_void_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value) +/*[clinic end generated code: output=984d0075b6038cc7 input=0e8b343fc19c77d4]*/ { PyObject *as_parameter; int res; @@ -1798,7 +1842,7 @@ c_void_p_from_param(PyObject *type, PyObject *value) if (value == Py_None) { Py_RETURN_NONE; } - ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + ctypes_state *st = get_module_state_by_class(cls->tp_base); /* Should probably allow buffer interface as well */ /* int, long */ @@ -1920,7 +1964,7 @@ c_void_p_from_param(PyObject *type, PyObject *value) return NULL; } if (as_parameter) { - value = c_void_p_from_param(type, as_parameter); + value = c_void_p_from_param_impl(type, cls, as_parameter); Py_DECREF(as_parameter); return value; } @@ -1930,9 +1974,9 @@ c_void_p_from_param(PyObject *type, PyObject *value) return NULL; } -static PyMethodDef c_void_p_method = { "from_param", c_void_p_from_param, METH_O }; -static PyMethodDef c_char_p_method = { "from_param", c_char_p_from_param, METH_O }; -static PyMethodDef c_wchar_p_method = { "from_param", c_wchar_p_from_param, METH_O }; +static PyMethodDef c_void_p_methods[] = {C_VOID_P_FROM_PARAM_METHODDEF {0}}; +static PyMethodDef c_char_p_methods[] = {C_CHAR_P_FROM_PARAM_METHODDEF {0}}; +static PyMethodDef c_wchar_p_methods[] = {C_WCHAR_P_FROM_PARAM_METHODDEF {0}}; static PyObject *CreateSwappedType(ctypes_state *st, PyTypeObject *type, PyObject *args, PyObject *kwds, @@ -2117,15 +2161,15 @@ PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds) if (((PyTypeObject *)self)->tp_base == st->Simple_Type) { switch (*proto_str) { case 'z': /* c_char_p */ - ml = &c_char_p_method; + ml = c_char_p_methods; stginfo->flags |= TYPEFLAG_ISPOINTER; break; case 'Z': /* c_wchar_p */ - ml = &c_wchar_p_method; + ml = c_wchar_p_methods; stginfo->flags |= TYPEFLAG_ISPOINTER; break; case 'P': /* c_void_p */ - ml = &c_void_p_method; + ml = c_void_p_methods; stginfo->flags |= TYPEFLAG_ISPOINTER; break; case 's': From 0bf6ad960b980c3b983be1656f7a322f1dc8723d Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 4 Apr 2024 11:52:15 +0900 Subject: [PATCH 24/38] AC2: the others --- Modules/_ctypes/_ctypes.c | 248 ++++++++---- Modules/_ctypes/clinic/_ctypes.c.h | 588 +++++++++++++++++++++++++++++ 2 files changed, 761 insertions(+), 75 deletions(-) create mode 100644 Modules/_ctypes/clinic/_ctypes.c.h diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 01557df221ac6c..ca117a1c9f2598 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -720,11 +720,23 @@ UnionType_init(PyObject *self, PyObject *args, PyObject *kwds) return StructUnionType_init(self, args, kwds, 0); } -PyDoc_STRVAR(from_address_doc, -"C.from_address(integer) -> C instance\naccess a C instance at the specified address"); +/*[clinic input] +_ctypes.CDataType.from_address as CDataType_from_address + + type: self + cls: defining_class + value: object + / + +C.from_address(integer) -> C instance + +Access a C instance at the specified address +[clinic start generated code]*/ static PyObject * -CDataType_from_address(PyObject *type, PyObject *value) +CDataType_from_address_impl(PyObject *type, PyTypeObject *cls, + PyObject *value) +/*[clinic end generated code: output=5be4a7c0d9aa6c74 input=104ed288a3ecab50]*/ { void *buf; if (!PyLong_Check(value)) { @@ -735,26 +747,37 @@ CDataType_from_address(PyObject *type, PyObject *value) buf = (void *)PyLong_AsVoidPtr(value); if (PyErr_Occurred()) return NULL; - ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + ctypes_state *st = get_module_state_by_class(cls); return PyCData_AtAddress(st, type, buf); } -PyDoc_STRVAR(from_buffer_doc, -"C.from_buffer(object, offset=0) -> C instance\ncreate a C instance from a writeable buffer"); - static int KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep); +/*[clinic input] +_ctypes.CDataType.from_buffer as CDataType_from_buffer + + type: self + cls: defining_class + obj: object + offset: Py_ssize_t = 0 + / + +C.from_buffer(object, offset=0) -> C instance + +Create a C instance from a writeable buffer. +[clinic start generated code]*/ + static PyObject * -CDataType_from_buffer(PyObject *type, PyObject *args) +CDataType_from_buffer_impl(PyObject *type, PyTypeObject *cls, PyObject *obj, + Py_ssize_t offset) +/*[clinic end generated code: output=57604e99635abd31 input=0f36cedd105ca28d]*/ { - PyObject *obj; PyObject *mv; PyObject *result; Py_buffer *buffer; - Py_ssize_t offset = 0; - ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + ctypes_state *st = get_module_state_by_class(cls); StgInfo *info; if (PyStgInfo_FromType(st, type, &info) < 0) { return NULL; @@ -764,9 +787,6 @@ CDataType_from_buffer(PyObject *type, PyObject *args) return NULL; } - if (!PyArg_ParseTuple(args, "O|n:from_buffer", &obj, &offset)) - return NULL; - mv = PyMemoryView_FromObject(obj); if (mv == NULL) return NULL; @@ -823,9 +843,6 @@ CDataType_from_buffer(PyObject *type, PyObject *args) return result; } -PyDoc_STRVAR(from_buffer_copy_doc, -"C.from_buffer_copy(object, offset=0) -> C instance\ncreate a C instance from a readable buffer"); - static inline PyObject * generic_pycdata_new(ctypes_state *st, PyTypeObject *type, PyObject *args, PyObject *kwds); @@ -833,14 +850,28 @@ generic_pycdata_new(ctypes_state *st, static PyObject * GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds); +/*[clinic input] +_ctypes.CDataType.from_buffer_copy as CDataType_from_buffer_copy + + type: self + cls: defining_class + buffer: Py_buffer + offset: Py_ssize_t = 0 + / + +C.from_buffer_copy(object, offset=0) -> C instance + +Create a C instance from a readable buffer. +[clinic start generated code]*/ + static PyObject * -CDataType_from_buffer_copy(PyObject *type, PyObject *args) +CDataType_from_buffer_copy_impl(PyObject *type, PyTypeObject *cls, + Py_buffer *buffer, Py_ssize_t offset) +/*[clinic end generated code: output=c8fc62b03e5cc6fa input=2a81e11b765a6253]*/ { - Py_buffer buffer; - Py_ssize_t offset = 0; PyObject *result; - ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + ctypes_state *st = get_module_state_by_class(cls); StgInfo *info; if (PyStgInfo_FromType(st, type, &info) < 0) { return NULL; @@ -850,54 +881,56 @@ CDataType_from_buffer_copy(PyObject *type, PyObject *args) return NULL; } - if (!PyArg_ParseTuple(args, "y*|n:from_buffer_copy", &buffer, &offset)) - return NULL; - if (offset < 0) { PyErr_SetString(PyExc_ValueError, "offset cannot be negative"); - PyBuffer_Release(&buffer); return NULL; } - if (info->size > buffer.len - offset) { + if (info->size > buffer->len - offset) { PyErr_Format(PyExc_ValueError, "Buffer size too small (%zd instead of at least %zd bytes)", - buffer.len, info->size + offset); - PyBuffer_Release(&buffer); + buffer->len, info->size + offset); return NULL; } if (PySys_Audit("ctypes.cdata/buffer", "nnn", - (Py_ssize_t)buffer.buf, buffer.len, offset) < 0) { - PyBuffer_Release(&buffer); + (Py_ssize_t)buffer->buf, buffer->len, offset) < 0) { return NULL; } result = generic_pycdata_new(st, (PyTypeObject *)type, NULL, NULL); if (result != NULL) { memcpy(((CDataObject *)result)->b_ptr, - (char *)buffer.buf + offset, info->size); + (char *)buffer->buf + offset, info->size); } - PyBuffer_Release(&buffer); return result; } -PyDoc_STRVAR(in_dll_doc, -"C.in_dll(dll, name) -> C instance\naccess a C instance in a dll"); +/*[clinic input] +_ctypes.CDataType.in_dll as CDataType_in_dll + + type: self + cls: defining_class + dll: object + name: str + / + +C.in_dll(dll, name) -> C instance + +Access a C instance in a dll +[clinic start generated code]*/ static PyObject * -CDataType_in_dll(PyObject *type, PyObject *args) +CDataType_in_dll_impl(PyObject *type, PyTypeObject *cls, PyObject *dll, + const char *name) +/*[clinic end generated code: output=d0e5c43b66bfa21f input=7fe5dc35a9b64423]*/ { - PyObject *dll; - char *name; PyObject *obj; void *handle; void *address; - if (!PyArg_ParseTuple(args, "Os:in_dll", &dll, &name)) - return NULL; - if (PySys_Audit("ctypes.dlsym", "O", args) < 0) { + if (PySys_Audit("ctypes.dlsym", "Os", dll, name) < 0) { return NULL; } @@ -946,11 +979,20 @@ CDataType_in_dll(PyObject *type, PyObject *args) return PyCData_AtAddress(st, type, address); } -PyDoc_STRVAR(from_param_doc, -"Convert a Python object into a function call parameter."); +/*[clinic input] +_ctypes.CDataType.from_param as CDataType_from_param + + type: self + cls: defining_class + value: object + / + +Convert a Python object into a function call parameter. +[clinic start generated code]*/ static PyObject * -CDataType_from_param(PyObject *type, PyObject *value) +CDataType_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value) +/*[clinic end generated code: output=8da9e34263309f9e input=275a52c4899ddff0]*/ { PyObject *as_parameter; int res = PyObject_IsInstance(value, type); @@ -959,7 +1001,7 @@ CDataType_from_param(PyObject *type, PyObject *value) if (res) { return Py_NewRef(value); } - ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + ctypes_state *st = get_module_state_by_class(cls); if (PyCArg_CheckExact(st, value)) { PyCArgObject *p = (PyCArgObject *)value; PyObject *ob = p->obj; @@ -989,7 +1031,7 @@ CDataType_from_param(PyObject *type, PyObject *value) return NULL; } if (as_parameter) { - value = CDataType_from_param(type, as_parameter); + value = CDataType_from_param_impl(type, cls, as_parameter); Py_DECREF(as_parameter); return value; } @@ -1001,11 +1043,11 @@ CDataType_from_param(PyObject *type, PyObject *value) } static PyMethodDef CDataType_methods[] = { - { "from_param", CDataType_from_param, METH_O, from_param_doc }, - { "from_address", CDataType_from_address, METH_O, from_address_doc }, - { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, }, - { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, - { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc }, + CDATATYPE_FROM_PARAM_METHODDEF + CDATATYPE_FROM_ADDRESS_METHODDEF + CDATATYPE_FROM_BUFFER_METHODDEF + CDATATYPE_FROM_BUFFER_COPY_METHODDEF + CDATATYPE_IN_DLL_METHODDEF { NULL, NULL }, }; @@ -1197,15 +1239,26 @@ PyCPointerType_init(PyObject *self, PyObject *args, PyObject *kwds) return 0; } +/*[clinic input] +_ctypes.PyCPointerType.set_type as PyCPointerType_set_type + + self: self(type="PyTypeObject *") + cls: defining_class + type: object + / +[clinic start generated code]*/ static PyObject * -PyCPointerType_set_type(PyTypeObject *self, PyObject *type) +PyCPointerType_set_type_impl(PyTypeObject *self, PyTypeObject *cls, + PyObject *type) +/*[clinic end generated code: output=51459d8f429a70ac input=67e1e8df921f123e]*/ + { PyObject *attrdict = PyType_GetDict(self); if (!attrdict) { return NULL; } - ctypes_state *st = get_module_state_by_def(Py_TYPE(self)); + ctypes_state *st = get_module_state_by_class(cls); StgInfo *info; if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) { Py_DECREF(attrdict); @@ -1234,15 +1287,28 @@ PyCPointerType_set_type(PyTypeObject *self, PyObject *type) static PyObject *_byref(ctypes_state *, PyObject *); +/*[clinic input] +_ctypes.PyCPointerType.from_param as PyCPointerType_from_param + + type: self + cls: defining_class + value: object + / + +Convert a Python object into a function call parameter. +[clinic start generated code]*/ + static PyObject * -PyCPointerType_from_param(PyObject *type, PyObject *value) +PyCPointerType_from_param_impl(PyObject *type, PyTypeObject *cls, + PyObject *value) +/*[clinic end generated code: output=a4b32d929aabaf64 input=6c231276e3997884]*/ { if (value == Py_None) { /* ConvParam will convert to a NULL pointer later */ return Py_NewRef(value); } - ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + ctypes_state *st = get_module_state_by_class(cls); StgInfo *typeinfo; if (PyStgInfo_FromType(st, type, &typeinfo) < 0) { return NULL; @@ -1284,16 +1350,16 @@ PyCPointerType_from_param(PyObject *type, PyObject *value) return Py_NewRef(value); } } - return CDataType_from_param(type, value); + return CDataType_from_param_impl(type, cls, value); } static PyMethodDef PyCPointerType_methods[] = { - { "from_address", CDataType_from_address, METH_O, from_address_doc }, - { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, }, - { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, - { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc}, - { "from_param", (PyCFunction)PyCPointerType_from_param, METH_O, from_param_doc}, - { "set_type", (PyCFunction)PyCPointerType_set_type, METH_O }, + CDATATYPE_FROM_ADDRESS_METHODDEF + CDATATYPE_FROM_BUFFER_METHODDEF + CDATATYPE_FROM_BUFFER_COPY_METHODDEF + CDATATYPE_IN_DLL_METHODDEF + PYCPOINTERTYPE_FROM_PARAM_METHODDEF + PYCPOINTERTYPE_SET_TYPE_METHODDEF { NULL, NULL }, }; @@ -2243,8 +2309,22 @@ PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds) * This is a *class method*. * Convert a parameter into something that ConvParam can handle. */ + +/*[clinic input] +_ctypes.PyCSimpleType.from_param as PyCSimpleType_from_param + + type: self + cls: defining_class + value: object + / + +Convert a Python object into a function call parameter. +[clinic start generated code]*/ + static PyObject * -PyCSimpleType_from_param(PyObject *type, PyObject *value) +PyCSimpleType_from_param_impl(PyObject *type, PyTypeObject *cls, + PyObject *value) +/*[clinic end generated code: output=8a8453d9663e3a2e input=61cc48ce3a87a570]*/ { const char *fmt; PyCArgObject *parg; @@ -2261,7 +2341,7 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value) return Py_NewRef(value); } - ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); + ctypes_state *st = get_module_state_by_class(cls); StgInfo *info; if (PyStgInfo_FromType(st, type, &info) < 0) { return NULL; @@ -2301,7 +2381,7 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value) Py_XDECREF(exc); return NULL; } - value = PyCSimpleType_from_param(type, as_parameter); + value = PyCSimpleType_from_param_impl(type, cls, as_parameter); _Py_LeaveRecursiveCall(); Py_DECREF(as_parameter); Py_XDECREF(exc); @@ -2317,11 +2397,11 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value) } static PyMethodDef PyCSimpleType_methods[] = { - { "from_param", PyCSimpleType_from_param, METH_O, from_param_doc }, - { "from_address", CDataType_from_address, METH_O, from_address_doc }, - { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, }, - { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, - { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc}, + PYCSIMPLETYPE_FROM_PARAM_METHODDEF + CDATATYPE_FROM_ADDRESS_METHODDEF + CDATATYPE_FROM_BUFFER_METHODDEF + CDATATYPE_FROM_BUFFER_COPY_METHODDEF + CDATATYPE_IN_DLL_METHODDEF { NULL, NULL }, }; @@ -2817,12 +2897,21 @@ PyCData_nohash(PyObject *self) return -1; } +/*[clinic input] +_ctypes.PyCData.__reduce__ as PyCData_reduce + + myself: self + cls: defining_class + / +[clinic start generated code]*/ + static PyObject * -PyCData_reduce(PyObject *myself, PyObject *args) +PyCData_reduce_impl(PyObject *myself, PyTypeObject *cls) +/*[clinic end generated code: output=1a025ccfdd8c935d input=34097a5226ea63c1]*/ { CDataObject *self = (CDataObject *)myself; - ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(myself))); + ctypes_state *st = get_module_state_by_class(cls); StgInfo *info; if (PyStgInfo_FromObject(st, myself, &info) < 0) { return NULL; @@ -2887,7 +2976,7 @@ PyCData_from_outparam(PyObject *self, PyObject *args) static PyMethodDef PyCData_methods[] = { { "__ctypes_from_outparam__", PyCData_from_outparam, METH_NOARGS, }, - { "__reduce__", PyCData_reduce, METH_NOARGS, }, + PYCDATA_REDUCE_METHODDEF { "__setstate__", PyCData_setstate, METH_VARARGS, }, { NULL, NULL }, }; @@ -4913,10 +5002,19 @@ static PyGetSetDef Simple_getsets[] = { { NULL, NULL } }; +/*[clinic input] +_ctypes.Simple.__ctypes_from_outparam__ as Simple_from_outparm + + self: self + cls: defining_class + / +[clinic start generated code]*/ + static PyObject * -Simple_from_outparm(PyObject *self, PyObject *args) +Simple_from_outparm_impl(PyObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=6c61d90da8aa9b4f input=0f362803fb4629d5]*/ { - ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); + ctypes_state *st = get_module_state_by_class(cls); if (_ctypes_simple_instance(st, (PyObject *)Py_TYPE(self))) { return Py_NewRef(self); } @@ -4925,7 +5023,7 @@ Simple_from_outparm(PyObject *self, PyObject *args) } static PyMethodDef Simple_methods[] = { - { "__ctypes_from_outparam__", Simple_from_outparm, METH_NOARGS, }, + SIMPLE_FROM_OUTPARM_METHODDEF { NULL, NULL }, }; diff --git a/Modules/_ctypes/clinic/_ctypes.c.h b/Modules/_ctypes/clinic/_ctypes.c.h new file mode 100644 index 00000000000000..842d70e64bf909 --- /dev/null +++ b/Modules/_ctypes/clinic/_ctypes.c.h @@ -0,0 +1,588 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() + +PyDoc_STRVAR(CDataType_from_address__doc__, +"from_address($self, value, /)\n" +"--\n" +"\n" +"C.from_address(integer) -> C instance\n" +"\n" +"Access a C instance at the specified address"); + +#define CDATATYPE_FROM_ADDRESS_METHODDEF \ + {"from_address", _PyCFunction_CAST(CDataType_from_address), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, CDataType_from_address__doc__}, + +static PyObject * +CDataType_from_address_impl(PyObject *type, PyTypeObject *cls, + PyObject *value); + +static PyObject * +CDataType_from_address(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "from_address", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + value = args[0]; + return_value = CDataType_from_address_impl(type, cls, value); + +exit: + return return_value; +} + +PyDoc_STRVAR(CDataType_from_buffer__doc__, +"from_buffer($self, obj, offset=0, /)\n" +"--\n" +"\n" +"C.from_buffer(object, offset=0) -> C instance\n" +"\n" +"Create a C instance from a writeable buffer."); + +#define CDATATYPE_FROM_BUFFER_METHODDEF \ + {"from_buffer", _PyCFunction_CAST(CDataType_from_buffer), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, CDataType_from_buffer__doc__}, + +static PyObject * +CDataType_from_buffer_impl(PyObject *type, PyTypeObject *cls, PyObject *obj, + Py_ssize_t offset); + +static PyObject * +CDataType_from_buffer(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", "", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "from_buffer", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *obj; + Py_ssize_t offset = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + obj = args[0]; + if (nargs < 2) { + goto skip_optional_posonly; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + offset = ival; + } +skip_optional_posonly: + return_value = CDataType_from_buffer_impl(type, cls, obj, offset); + +exit: + return return_value; +} + +PyDoc_STRVAR(CDataType_from_buffer_copy__doc__, +"from_buffer_copy($self, buffer, offset=0, /)\n" +"--\n" +"\n" +"C.from_buffer_copy(object, offset=0) -> C instance\n" +"\n" +"Create a C instance from a readable buffer."); + +#define CDATATYPE_FROM_BUFFER_COPY_METHODDEF \ + {"from_buffer_copy", _PyCFunction_CAST(CDataType_from_buffer_copy), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, CDataType_from_buffer_copy__doc__}, + +static PyObject * +CDataType_from_buffer_copy_impl(PyObject *type, PyTypeObject *cls, + Py_buffer *buffer, Py_ssize_t offset); + +static PyObject * +CDataType_from_buffer_copy(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", "", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "from_buffer_copy", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_buffer buffer = {NULL, NULL}; + Py_ssize_t offset = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (PyObject_GetBuffer(args[0], &buffer, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (nargs < 2) { + goto skip_optional_posonly; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + offset = ival; + } +skip_optional_posonly: + return_value = CDataType_from_buffer_copy_impl(type, cls, &buffer, offset); + +exit: + /* Cleanup for buffer */ + if (buffer.obj) { + PyBuffer_Release(&buffer); + } + + return return_value; +} + +PyDoc_STRVAR(CDataType_in_dll__doc__, +"in_dll($self, dll, name, /)\n" +"--\n" +"\n" +"C.in_dll(dll, name) -> C instance\n" +"\n" +"Access a C instance in a dll"); + +#define CDATATYPE_IN_DLL_METHODDEF \ + {"in_dll", _PyCFunction_CAST(CDataType_in_dll), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, CDataType_in_dll__doc__}, + +static PyObject * +CDataType_in_dll_impl(PyObject *type, PyTypeObject *cls, PyObject *dll, + const char *name); + +static PyObject * +CDataType_in_dll(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", "", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "in_dll", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *dll; + const char *name; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + dll = args[0]; + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("in_dll", "argument 2", "str", args[1]); + goto exit; + } + Py_ssize_t name_length; + name = PyUnicode_AsUTF8AndSize(args[1], &name_length); + if (name == NULL) { + goto exit; + } + if (strlen(name) != (size_t)name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = CDataType_in_dll_impl(type, cls, dll, name); + +exit: + return return_value; +} + +PyDoc_STRVAR(CDataType_from_param__doc__, +"from_param($self, value, /)\n" +"--\n" +"\n" +"Convert a Python object into a function call parameter."); + +#define CDATATYPE_FROM_PARAM_METHODDEF \ + {"from_param", _PyCFunction_CAST(CDataType_from_param), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, CDataType_from_param__doc__}, + +static PyObject * +CDataType_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value); + +static PyObject * +CDataType_from_param(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "from_param", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + value = args[0]; + return_value = CDataType_from_param_impl(type, cls, value); + +exit: + return return_value; +} + +PyDoc_STRVAR(PyCPointerType_set_type__doc__, +"set_type($self, type, /)\n" +"--\n" +"\n"); + +#define PYCPOINTERTYPE_SET_TYPE_METHODDEF \ + {"set_type", _PyCFunction_CAST(PyCPointerType_set_type), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, PyCPointerType_set_type__doc__}, + +static PyObject * +PyCPointerType_set_type_impl(PyTypeObject *self, PyTypeObject *cls, + PyObject *type); + +static PyObject * +PyCPointerType_set_type(PyTypeObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "set_type", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *type; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + type = args[0]; + return_value = PyCPointerType_set_type_impl(self, cls, type); + +exit: + return return_value; +} + +PyDoc_STRVAR(PyCPointerType_from_param__doc__, +"from_param($self, value, /)\n" +"--\n" +"\n" +"Convert a Python object into a function call parameter."); + +#define PYCPOINTERTYPE_FROM_PARAM_METHODDEF \ + {"from_param", _PyCFunction_CAST(PyCPointerType_from_param), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, PyCPointerType_from_param__doc__}, + +static PyObject * +PyCPointerType_from_param_impl(PyObject *type, PyTypeObject *cls, + PyObject *value); + +static PyObject * +PyCPointerType_from_param(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "from_param", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + value = args[0]; + return_value = PyCPointerType_from_param_impl(type, cls, value); + +exit: + return return_value; +} + +PyDoc_STRVAR(c_wchar_p_from_param__doc__, +"from_param($self, value, /)\n" +"--\n" +"\n"); + +#define C_WCHAR_P_FROM_PARAM_METHODDEF \ + {"from_param", _PyCFunction_CAST(c_wchar_p_from_param), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, c_wchar_p_from_param__doc__}, + +static PyObject * +c_wchar_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value); + +static PyObject * +c_wchar_p_from_param(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "from_param", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + value = args[0]; + return_value = c_wchar_p_from_param_impl(type, cls, value); + +exit: + return return_value; +} + +PyDoc_STRVAR(c_char_p_from_param__doc__, +"from_param($self, value, /)\n" +"--\n" +"\n"); + +#define C_CHAR_P_FROM_PARAM_METHODDEF \ + {"from_param", _PyCFunction_CAST(c_char_p_from_param), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, c_char_p_from_param__doc__}, + +static PyObject * +c_char_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value); + +static PyObject * +c_char_p_from_param(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "from_param", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + value = args[0]; + return_value = c_char_p_from_param_impl(type, cls, value); + +exit: + return return_value; +} + +PyDoc_STRVAR(c_void_p_from_param__doc__, +"from_param($self, value, /)\n" +"--\n" +"\n"); + +#define C_VOID_P_FROM_PARAM_METHODDEF \ + {"from_param", _PyCFunction_CAST(c_void_p_from_param), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, c_void_p_from_param__doc__}, + +static PyObject * +c_void_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value); + +static PyObject * +c_void_p_from_param(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "from_param", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + value = args[0]; + return_value = c_void_p_from_param_impl(type, cls, value); + +exit: + return return_value; +} + +PyDoc_STRVAR(PyCSimpleType_from_param__doc__, +"from_param($self, value, /)\n" +"--\n" +"\n" +"Convert a Python object into a function call parameter."); + +#define PYCSIMPLETYPE_FROM_PARAM_METHODDEF \ + {"from_param", _PyCFunction_CAST(PyCSimpleType_from_param), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, PyCSimpleType_from_param__doc__}, + +static PyObject * +PyCSimpleType_from_param_impl(PyObject *type, PyTypeObject *cls, + PyObject *value); + +static PyObject * +PyCSimpleType_from_param(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "from_param", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + value = args[0]; + return_value = PyCSimpleType_from_param_impl(type, cls, value); + +exit: + return return_value; +} + +PyDoc_STRVAR(PyCData_reduce__doc__, +"__reduce__($self, /)\n" +"--\n" +"\n"); + +#define PYCDATA_REDUCE_METHODDEF \ + {"__reduce__", _PyCFunction_CAST(PyCData_reduce), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, PyCData_reduce__doc__}, + +static PyObject * +PyCData_reduce_impl(PyObject *myself, PyTypeObject *cls); + +static PyObject * +PyCData_reduce(PyObject *myself, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) { + PyErr_SetString(PyExc_TypeError, "__reduce__() takes no arguments"); + return NULL; + } + return PyCData_reduce_impl(myself, cls); +} + +PyDoc_STRVAR(Simple_from_outparm__doc__, +"__ctypes_from_outparam__($self, /)\n" +"--\n" +"\n"); + +#define SIMPLE_FROM_OUTPARM_METHODDEF \ + {"__ctypes_from_outparam__", _PyCFunction_CAST(Simple_from_outparm), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, Simple_from_outparm__doc__}, + +static PyObject * +Simple_from_outparm_impl(PyObject *self, PyTypeObject *cls); + +static PyObject * +Simple_from_outparm(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) { + PyErr_SetString(PyExc_TypeError, "__ctypes_from_outparam__() takes no arguments"); + return NULL; + } + return Simple_from_outparm_impl(self, cls); +} +/*[clinic end generated code: output=1bfb1ed8f85e1906 input=a9049054013a1b77]*/ From 149d3a0703f322f01620405ab647374e2f26b971 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 4 Apr 2024 13:19:51 +0900 Subject: [PATCH 25/38] apply suggested AC conv (CType_Type) --- Modules/_ctypes/_ctypes.c | 27 ++++++++++++++++++--------- Modules/_ctypes/clinic/_ctypes.c.h | 24 +++++++++++++++++++++++- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index ca117a1c9f2598..829aaf853deb08 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -128,16 +128,17 @@ bytes(cdata) /*[clinic input] module _ctypes +class _ctypes.CType_Type "PyObject *" "st->CType_Type" class _ctypes.CDataType "PyObject *" "" -class _ctypes.PyCPointerType "PyObject *" "PyCPointerType_Type" -class _ctypes.PyCSimpleType "PyObject *" "PyCSimpleType_Type" -class _ctypes.PyCData "PyObject *" "PyCData_Type" -class _ctypes.Simple "PyObject *" "Simple_Type" +class _ctypes.PyCPointerType "PyObject *" "st->PyCPointerType_Type" +class _ctypes.PyCSimpleType "PyObject *" "st->PyCSimpleType_Type" +class _ctypes.PyCData "PyObject *" "st->PyCData_Type" +class _ctypes.Simple "PyObject *" "st->Simple_Type" class _ctypes.c_char_p "PyObject *" "" class _ctypes.c_wchar_p "PyObject *" "" class _ctypes.c_void_p "PyObject *" "" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=93e86f795c9444ba]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=76aba021756e47b7]*/ #include "clinic/_ctypes.c.h" @@ -524,13 +525,22 @@ CType_Type_dealloc(PyObject *self) Py_DECREF(tp); } +/*[clinic input] +_ctypes.CType_Type.__sizeof__ + + cls: defining_class + / +Return memory consumption of the type object. +[clinic start generated code]*/ + static PyObject * -CType_Type_sizeof(PyObject *self) +_ctypes_CType_Type___sizeof___impl(PyObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=c68c235be84d03f3 input=d064433b6110d1ce]*/ { Py_ssize_t size = Py_TYPE(self)->tp_basicsize; size += Py_TYPE(self)->tp_itemsize * Py_SIZE(self); - ctypes_state *st = get_module_state_by_def(Py_TYPE(self)); + ctypes_state *st = get_module_state_by_class(cls); StgInfo *info; if (PyStgInfo_FromType(st, self, &info) < 0) { return NULL; @@ -553,8 +563,7 @@ 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.")}, + _CTYPES_CTYPE_TYPE___SIZEOF___METHODDEF {0}, }; diff --git a/Modules/_ctypes/clinic/_ctypes.c.h b/Modules/_ctypes/clinic/_ctypes.c.h index 842d70e64bf909..ae54949f0f7c6b 100644 --- a/Modules/_ctypes/clinic/_ctypes.c.h +++ b/Modules/_ctypes/clinic/_ctypes.c.h @@ -5,6 +5,28 @@ preserve #include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() +PyDoc_STRVAR(_ctypes_CType_Type___sizeof____doc__, +"__sizeof__($self, /)\n" +"--\n" +"\n" +"Return memory consumption of the type object."); + +#define _CTYPES_CTYPE_TYPE___SIZEOF___METHODDEF \ + {"__sizeof__", _PyCFunction_CAST(_ctypes_CType_Type___sizeof__), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _ctypes_CType_Type___sizeof____doc__}, + +static PyObject * +_ctypes_CType_Type___sizeof___impl(PyObject *self, PyTypeObject *cls); + +static PyObject * +_ctypes_CType_Type___sizeof__(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) { + PyErr_SetString(PyExc_TypeError, "__sizeof__() takes no arguments"); + return NULL; + } + return _ctypes_CType_Type___sizeof___impl(self, cls); +} + PyDoc_STRVAR(CDataType_from_address__doc__, "from_address($self, value, /)\n" "--\n" @@ -585,4 +607,4 @@ Simple_from_outparm(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py } return Simple_from_outparm_impl(self, cls); } -/*[clinic end generated code: output=1bfb1ed8f85e1906 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d9632f894878669a input=a9049054013a1b77]*/ From 10426965b14793ab8cf1c105dd679868d522b1bb Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 4 Apr 2024 18:46:53 +0900 Subject: [PATCH 26/38] add missing test.support.script_helper --- Lib/test/test_ctypes/test_refcounts.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_ctypes/test_refcounts.py b/Lib/test/test_ctypes/test_refcounts.py index 005f2870a7b523..012722d8486218 100644 --- a/Lib/test/test_ctypes/test_refcounts.py +++ b/Lib/test/test_ctypes/test_refcounts.py @@ -4,6 +4,7 @@ import unittest from test import support from test.support import import_helper +from test.support import script_helper _ctypes_test = import_helper.import_module("_ctypes_test") From 8107885fa590879f8966648750737c4bd8bcf904 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 4 Apr 2024 19:40:57 +0900 Subject: [PATCH 27/38] AC: split class imputs --- Modules/_ctypes/_ctypes.c | 57 +++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index d65e659eef134b..cb042e52a19682 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -128,17 +128,8 @@ bytes(cdata) /*[clinic input] module _ctypes -class _ctypes.CType_Type "PyObject *" "st->CType_Type" -class _ctypes.CDataType "PyObject *" "" -class _ctypes.PyCPointerType "PyObject *" "st->PyCPointerType_Type" -class _ctypes.PyCSimpleType "PyObject *" "st->PyCSimpleType_Type" -class _ctypes.PyCData "PyObject *" "st->PyCData_Type" -class _ctypes.Simple "PyObject *" "st->Simple_Type" -class _ctypes.c_char_p "PyObject *" "" -class _ctypes.c_wchar_p "PyObject *" "" -class _ctypes.c_void_p "PyObject *" "" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=76aba021756e47b7]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=476a19c49b31a75c]*/ #include "clinic/_ctypes.c.h" @@ -734,6 +725,12 @@ UnionType_init(PyObject *self, PyObject *args, PyObject *kwds) return StructUnionType_init(self, args, kwds, 0); } +/*[clinic input] +class _ctypes.CDataType "PyObject *" "" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=50e231c00c3d5b3b]*/ + + /*[clinic input] _ctypes.CDataType.from_address as CDataType_from_address @@ -1150,6 +1147,12 @@ size property/method, and the sequence protocol. */ +/*[clinic input] +class _ctypes.PyCPointerType "PyObject *" "st->PyCPointerType_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f55cffad4be4031c]*/ + + static int PyCPointerType_SetProto(ctypes_state *st, StgInfo *stginfo, PyObject *proto) { @@ -1266,7 +1269,6 @@ static PyObject * PyCPointerType_set_type_impl(PyTypeObject *self, PyTypeObject *cls, PyObject *type) /*[clinic end generated code: output=51459d8f429a70ac input=67e1e8df921f123e]*/ - { PyObject *attrdict = PyType_GetDict(self); if (!attrdict) { @@ -1732,6 +1734,26 @@ _type_ attribute. */ +/*[clinic input] +class _ctypes.PyCSimpleType "PyObject *" "st->PyCSimpleType_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d4e70c88c2b66eb4]*/ + +/*[clinic input] +class _ctypes.c_wchar_p "PyObject *" "" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9d20886e76c8d270]*/ + +/*[clinic input] +class _ctypes.c_char_p "PyObject *" "" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d001f38521ae2e8a]*/ + +/*[clinic input] +class _ctypes.c_void_p "PyObject *" "" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2627dadc498784b7]*/ + static const char SIMPLE_TYPE_CHARS[] = "cbBhHiIlLdfuzZqQPXOv?g"; /*[clinic input] @@ -2794,6 +2816,13 @@ KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep) /* PyCData_Type */ + +/*[clinic input] +class _ctypes.PyCData "PyObject *" "st->PyCData_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=253e5d9a1cbbe944]*/ + + static int PyCData_traverse(CDataObject *self, visitproc visit, void *arg) { @@ -4959,6 +4988,12 @@ PyCArrayType_from_ctype(ctypes_state *st, PyObject *itemtype, Py_ssize_t length) Simple_Type */ +/*[clinic input] +class _ctypes.Simple "PyObject *" "st->Simple_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=29f54d201863e234]*/ + + static int Simple_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) { From bcdf867f64140fdef7b33850473f4f9fa0b8b1c8 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 4 Apr 2024 20:22:39 +0900 Subject: [PATCH 28/38] periods --- Modules/_ctypes/_ctypes.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index cb042e52a19682..fd00f37d84e468 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -130,7 +130,6 @@ bytes(cdata) module _ctypes [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=476a19c49b31a75c]*/ - #include "clinic/_ctypes.c.h" /****************************************************************/ @@ -741,7 +740,7 @@ _ctypes.CDataType.from_address as CDataType_from_address C.from_address(integer) -> C instance -Access a C instance at the specified address +Access a C instance at the specified address. [clinic start generated code]*/ static PyObject * @@ -929,7 +928,7 @@ _ctypes.CDataType.in_dll as CDataType_in_dll C.in_dll(dll, name) -> C instance -Access a C instance in a dll +Access a C instance in a dll. [clinic start generated code]*/ static PyObject * From 39c91b43934819bd3f35a0cfbcc98b7d09f00803 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 4 Apr 2024 21:05:50 +0900 Subject: [PATCH 29/38] update AC checksums --- Modules/_ctypes/_ctypes.c | 4 ++-- Modules/_ctypes/clinic/_ctypes.c.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index fd00f37d84e468..a041311c68ab15 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -746,7 +746,7 @@ Access a C instance at the specified address. static PyObject * CDataType_from_address_impl(PyObject *type, PyTypeObject *cls, PyObject *value) -/*[clinic end generated code: output=5be4a7c0d9aa6c74 input=104ed288a3ecab50]*/ +/*[clinic end generated code: output=5be4a7c0d9aa6c74 input=827a22cefe380c01]*/ { void *buf; if (!PyLong_Check(value)) { @@ -934,7 +934,7 @@ Access a C instance in a dll. static PyObject * CDataType_in_dll_impl(PyObject *type, PyTypeObject *cls, PyObject *dll, const char *name) -/*[clinic end generated code: output=d0e5c43b66bfa21f input=7fe5dc35a9b64423]*/ +/*[clinic end generated code: output=d0e5c43b66bfa21f input=f85bf281477042b4]*/ { PyObject *obj; void *handle; diff --git a/Modules/_ctypes/clinic/_ctypes.c.h b/Modules/_ctypes/clinic/_ctypes.c.h index ae54949f0f7c6b..98a84cc14f4386 100644 --- a/Modules/_ctypes/clinic/_ctypes.c.h +++ b/Modules/_ctypes/clinic/_ctypes.c.h @@ -33,7 +33,7 @@ PyDoc_STRVAR(CDataType_from_address__doc__, "\n" "C.from_address(integer) -> C instance\n" "\n" -"Access a C instance at the specified address"); +"Access a C instance at the specified address."); #define CDATATYPE_FROM_ADDRESS_METHODDEF \ {"from_address", _PyCFunction_CAST(CDataType_from_address), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, CDataType_from_address__doc__}, @@ -212,7 +212,7 @@ PyDoc_STRVAR(CDataType_in_dll__doc__, "\n" "C.in_dll(dll, name) -> C instance\n" "\n" -"Access a C instance in a dll"); +"Access a C instance in a dll."); #define CDATATYPE_IN_DLL_METHODDEF \ {"in_dll", _PyCFunction_CAST(CDataType_in_dll), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, CDataType_in_dll__doc__}, @@ -607,4 +607,4 @@ Simple_from_outparm(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py } return Simple_from_outparm_impl(self, cls); } -/*[clinic end generated code: output=d9632f894878669a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9c6539a3559e6088 input=a9049054013a1b77]*/ From 5db3c426da62c5295317f6e0f2682b767bfd0367 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Fri, 5 Apr 2024 16:38:22 +0900 Subject: [PATCH 30/38] fill type names --- Modules/_ctypes/_ctypes.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index a041311c68ab15..051ce0bf81dde8 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -725,9 +725,9 @@ UnionType_init(PyObject *self, PyObject *args, PyObject *kwds) } /*[clinic input] -class _ctypes.CDataType "PyObject *" "" +class _ctypes.CDataType "PyObject *" "st->CType_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=50e231c00c3d5b3b]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a5629668227ced6c]*/ /*[clinic input] @@ -1739,19 +1739,19 @@ class _ctypes.PyCSimpleType "PyObject *" "st->PyCSimpleType_Type" /*[clinic end generated code: output=da39a3ee5e6b4b0d input=d4e70c88c2b66eb4]*/ /*[clinic input] -class _ctypes.c_wchar_p "PyObject *" "" +class _ctypes.c_wchar_p "PyObject *" "st->PyCSimpleType_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9d20886e76c8d270]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ad67842bc81b56a6]*/ /*[clinic input] -class _ctypes.c_char_p "PyObject *" "" +class _ctypes.c_char_p "PyObject *" "st->PyCSimpleType_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d001f38521ae2e8a]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9a97029952caab32]*/ /*[clinic input] -class _ctypes.c_void_p "PyObject *" "" +class _ctypes.c_void_p "PyObject *" "st->PyCSimpleType_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2627dadc498784b7]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=fd4534ee51ddf049]*/ static const char SIMPLE_TYPE_CHARS[] = "cbBhHiIlLdfuzZqQPXOv?g"; From 40cec340ed9429837d410941221e386e95a310df Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Fri, 5 Apr 2024 20:54:14 +0900 Subject: [PATCH 31/38] AC: class default module state getters --- Modules/_ctypes/_ctypes.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 051ce0bf81dde8..ce9429b8183159 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -132,6 +132,9 @@ module _ctypes /*[clinic end generated code: output=da39a3ee5e6b4b0d input=476a19c49b31a75c]*/ #include "clinic/_ctypes.c.h" +#define clinic_state() (get_module_state_by_class(cls)) +#define clinic_state_sub() (get_module_state_by_class(cls->base)) + /****************************************************************/ typedef struct { @@ -442,9 +445,9 @@ static PyType_Spec structparam_spec = { */ /*[clinic input] -class _ctypes.CType_Type "PyObject *" "st->CType_Type" +class _ctypes.CType_Type "PyObject *" "clinic_state()->CType_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f385b8663b8be200]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8389fc5b74a84f2a]*/ static int CType_Type_traverse(PyObject *self, visitproc visit, void *arg) @@ -725,9 +728,9 @@ UnionType_init(PyObject *self, PyObject *args, PyObject *kwds) } /*[clinic input] -class _ctypes.CDataType "PyObject *" "st->CType_Type" +class _ctypes.CDataType "PyObject *" "clinic_state()->CType_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a5629668227ced6c]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=466a505a93d73156]*/ /*[clinic input] @@ -1147,9 +1150,9 @@ size property/method, and the sequence protocol. */ /*[clinic input] -class _ctypes.PyCPointerType "PyObject *" "st->PyCPointerType_Type" +class _ctypes.PyCPointerType "PyObject *" "clinic_state()->PyCPointerType_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f55cffad4be4031c]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c45e96c1f7645ab7]*/ static int @@ -1734,24 +1737,24 @@ _type_ attribute. */ /*[clinic input] -class _ctypes.PyCSimpleType "PyObject *" "st->PyCSimpleType_Type" +class _ctypes.PyCSimpleType "PyObject *" "clinic_state()->PyCSimpleType_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d4e70c88c2b66eb4]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d5a45772668e7f49]*/ /*[clinic input] -class _ctypes.c_wchar_p "PyObject *" "st->PyCSimpleType_Type" +class _ctypes.c_wchar_p "PyObject *" "clinic_state_sub()->PyCSimpleType_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ad67842bc81b56a6]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=468de7283d622d47]*/ /*[clinic input] -class _ctypes.c_char_p "PyObject *" "st->PyCSimpleType_Type" +class _ctypes.c_char_p "PyObject *" "clinic_state_sub()->PyCSimpleType_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9a97029952caab32]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e750865616e7dcea]*/ /*[clinic input] -class _ctypes.c_void_p "PyObject *" "st->PyCSimpleType_Type" +class _ctypes.c_void_p "PyObject *" "clinic_state_sub()->PyCSimpleType_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=fd4534ee51ddf049]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=dd4d9646c56f43a9]*/ static const char SIMPLE_TYPE_CHARS[] = "cbBhHiIlLdfuzZqQPXOv?g"; @@ -2817,9 +2820,9 @@ KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep) */ /*[clinic input] -class _ctypes.PyCData "PyObject *" "st->PyCData_Type" +class _ctypes.PyCData "PyObject *" "clinic_state()->PyCData_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=253e5d9a1cbbe944]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ac13df38dee3c22c]*/ static int @@ -4988,9 +4991,9 @@ PyCArrayType_from_ctype(ctypes_state *st, PyObject *itemtype, Py_ssize_t length) */ /*[clinic input] -class _ctypes.Simple "PyObject *" "st->Simple_Type" +class _ctypes.Simple "PyObject *" "clinic_state()->Simple_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=29f54d201863e234]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=016c476c7aa8b8a8]*/ static int From 893a98161b00e37c748736c0679a39d21ee254b1 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Fri, 5 Apr 2024 21:02:36 +0900 Subject: [PATCH 32/38] typo --- Modules/_ctypes/_ctypes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index ce9429b8183159..95c7ccb24fa2d9 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -133,7 +133,7 @@ module _ctypes #include "clinic/_ctypes.c.h" #define clinic_state() (get_module_state_by_class(cls)) -#define clinic_state_sub() (get_module_state_by_class(cls->base)) +#define clinic_state_sub() (get_module_state_by_class(cls->tp_base)) /****************************************************************/ From 807c6c041b3569c5b7e5d3db76805231ced97778 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Fri, 5 Apr 2024 21:18:51 +0900 Subject: [PATCH 33/38] move define up --- Modules/_ctypes/_ctypes.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 95c7ccb24fa2d9..64a5c95bc0df3e 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -130,10 +130,12 @@ bytes(cdata) module _ctypes [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=476a19c49b31a75c]*/ -#include "clinic/_ctypes.c.h" #define clinic_state() (get_module_state_by_class(cls)) #define clinic_state_sub() (get_module_state_by_class(cls->tp_base)) +#include "clinic/_ctypes.c.h" +#undef clinic_state +#undef clinic_state_sub /****************************************************************/ From f58ed21962ae09c5e0eaeabaf8e7a229c7430791 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Tue, 9 Apr 2024 21:18:11 +0900 Subject: [PATCH 34/38] Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED Co-authored-by: Petr Viktorin --- Modules/_ctypes/_ctypes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 64a5c95bc0df3e..3cb0b24668eb2a 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -5947,7 +5947,7 @@ module_free(void *module) static PyModuleDef_Slot module_slots[] = { {Py_mod_exec, _ctypes_mod_exec}, - {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, {0, NULL} }; From cb88db3f41472f745e89ded3a2613f06ed9a72d6 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:11:50 +0900 Subject: [PATCH 35/38] Move PyGILState_Ensure/Release --- Modules/_ctypes/callbacks.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 9fedeab43f866e..aff48bd52c10e6 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -149,7 +149,6 @@ static void _CallPythonObject(ctypes_state *st, Py_ssize_t i = 0, j = 0, nargs = 0; PyObject *error_object = NULL; int *space; - PyGILState_STATE state = PyGILState_Ensure(); assert(PyTuple_Check(converters)); nargs = PyTuple_GET_SIZE(converters); @@ -294,7 +293,6 @@ static void _CallPythonObject(ctypes_state *st, for (j = 0; j < i; j++) { Py_DECREF(args[j]); } - PyGILState_Release(state); } static void closure_fcn(ffi_cif *cif, @@ -302,6 +300,9 @@ static void closure_fcn(ffi_cif *cif, void **args, void *userdata) { + // needs the GIL to get the module state + PyGILState_STATE state = PyGILState_Ensure(); + CThunkObject *p = (CThunkObject *)userdata; ctypes_state *st = get_module_state_by_class(Py_TYPE(p)); @@ -313,6 +314,8 @@ static void closure_fcn(ffi_cif *cif, p->converters, p->flags, args); + + PyGILState_Release(state); } static CThunkObject* CThunkObject_new(ctypes_state *st, Py_ssize_t nargs) From 4237557008e3f618dfd00329bdbd1491115b2e55 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Wed, 10 Apr 2024 00:27:50 +0900 Subject: [PATCH 36/38] fix a comment --- Modules/_ctypes/callbacks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index aff48bd52c10e6..7b9f6437c7d55f 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -136,6 +136,8 @@ TryAddRef(PyObject *cnv, CDataObject *obj) * Call the python object with all arguments * */ + +// BEWARE: The GIL needs to be held throughout the function static void _CallPythonObject(ctypes_state *st, void *mem, ffi_type *restype, @@ -300,7 +302,6 @@ static void closure_fcn(ffi_cif *cif, void **args, void *userdata) { - // needs the GIL to get the module state PyGILState_STATE state = PyGILState_Ensure(); CThunkObject *p = (CThunkObject *)userdata; From 03cffa91f8554daf26a92a4de2aba54e0ecc2089 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Wed, 10 Apr 2024 19:29:39 +0900 Subject: [PATCH 37/38] change NEWS (PEP 687 -> 489) --- .../next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst b/Misc/NEWS.d/next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst index 466e1058bd282d..80dfe66b80200c 100644 --- a/Misc/NEWS.d/next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst +++ b/Misc/NEWS.d/next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst @@ -1 +1 @@ -Isolate :mod:`!_ctypes` (apply :pep:`687`). +Convert :mod:`!_ctypes` to multi-phase initialisation (pep:`489`). From 76a2b8c0dc247be4343b1ee9adeb542caec18bc2 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Wed, 10 Apr 2024 19:31:30 +0900 Subject: [PATCH 38/38] typo --- .../next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst b/Misc/NEWS.d/next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst index 80dfe66b80200c..36810bd815c502 100644 --- a/Misc/NEWS.d/next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst +++ b/Misc/NEWS.d/next/Library/2024-03-29-12-21-40.gh-issue-117142.U0agfh.rst @@ -1 +1 @@ -Convert :mod:`!_ctypes` to multi-phase initialisation (pep:`489`). +Convert :mod:`!_ctypes` to multi-phase initialisation (:pep:`489`).