]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-117142: ctypes: Migrate global vars to module state (GH-117189)
authorneonene <53406459+neonene@users.noreply.github.com>
Fri, 29 Mar 2024 09:40:48 +0000 (18:40 +0900)
committerGitHub <noreply@github.com>
Fri, 29 Mar 2024 09:40:48 +0000 (10:40 +0100)
Modules/_ctypes/_ctypes.c
Modules/_ctypes/callbacks.c
Modules/_ctypes/callproc.c
Modules/_ctypes/cfield.c
Modules/_ctypes/ctypes.h
Modules/_ctypes/stgdict.c
Tools/c-analyzer/cpython/globals-to-fix.tsv

index af094a0fb59e2764787a8f8e5aa3fe8ef626f6ca..6bd1893480027c6b2e2c0ca3b02859298907ba9d 100644 (file)
@@ -128,15 +128,6 @@ bytes(cdata)
 
 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;
-
 
 /****************************************************************/
 
@@ -208,14 +199,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;
@@ -562,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;
@@ -578,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) {
@@ -594,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);
@@ -715,7 +703,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 = GLOBAL_STATE();
+    return PyCData_AtAddress(st, type, buf);
 }
 
 PyDoc_STRVAR(from_buffer_doc,
@@ -788,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;
@@ -805,6 +794,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 *
+generic_pycdata_new(ctypes_state *st,
+                    PyTypeObject *type, PyObject *args, PyObject *kwds);
+
 static PyObject *
 GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
 
@@ -849,7 +842,7 @@ CDataType_from_buffer_copy(PyObject *type, PyObject *args)
         return NULL;
     }
 
-    result = GenericPyCData_new((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);
@@ -917,7 +910,8 @@ CDataType_in_dll(PyObject *type, PyObject *args)
         return NULL;
     }
 #endif
-    return PyCData_AtAddress(type, address);
+    ctypes_state *st = GLOBAL_STATE();
+    return PyCData_AtAddress(st, type, address);
 }
 
 PyDoc_STRVAR(from_param_doc,
@@ -990,7 +984,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 = GLOBAL_STATE();
+    return PyCArrayType_from_ctype(st, self, length);
 }
 
 static int
@@ -1106,9 +1101,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");
@@ -1129,11 +1123,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;
 
@@ -1176,7 +1170,7 @@ PyCPointerType_init(PyObject *self, PyObject *args, PyObject *kwds)
     }
     if (proto) {
         const char *current_format;
-        if (-1 == PyCPointerType_SetProto(stginfo, proto)) {
+        if (PyCPointerType_SetProto(st, stginfo, proto) < 0) {
             Py_DECREF(proto);
             return -1;
         }
@@ -1230,7 +1224,7 @@ PyCPointerType_set_type(PyTypeObject *self, PyObject *type)
         return NULL;
     }
 
-    if (-1 == PyCPointerType_SetProto(info, type)) {
+    if (PyCPointerType_SetProto(st, info, type) < 0) {
         Py_DECREF(attrdict);
         return NULL;
     }
@@ -1244,7 +1238,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)
@@ -1272,7 +1266,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:
@@ -1506,9 +1500,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';
@@ -1684,11 +1678,12 @@ c_wchar_p_from_param(PyObject *type, PyObject *value)
     if (value == Py_None) {
         Py_RETURN_NONE;
     }
+    ctypes_state *st = GLOBAL_STATE();
     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;
@@ -1706,7 +1701,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;
@@ -1758,11 +1752,12 @@ c_char_p_from_param(PyObject *type, PyObject *value)
     if (value == Py_None) {
         Py_RETURN_NONE;
     }
+    ctypes_state *st = GLOBAL_STATE();
     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;
@@ -1780,7 +1775,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;
@@ -1834,13 +1828,15 @@ c_void_p_from_param(PyObject *type, PyObject *value)
     if (value == Py_None) {
         Py_RETURN_NONE;
     }
+    ctypes_state *st = GLOBAL_STATE();
+
     /* 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;
@@ -1858,7 +1854,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;
@@ -1875,7 +1871,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;
@@ -1895,7 +1891,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 */
@@ -1914,7 +1909,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;
@@ -1939,7 +1934,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;
@@ -1969,32 +1964,33 @@ 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;
@@ -2014,8 +2010,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);
@@ -2035,13 +2029,12 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject
 }
 
 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;
@@ -2053,7 +2046,7 @@ PyCSimpleType_paramfunc(CDataObject *self)
     fd = _ctypes_get_fielddesc(fmt);
     assert(fd);
 
-    parg = PyCArgObject_new();
+    parg = PyCArgObject_new(st);
     if (parg == NULL)
         return NULL;
 
@@ -2198,7 +2191,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;
@@ -2272,7 +2265,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;
 
@@ -2343,7 +2336,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;
@@ -2358,7 +2351,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;
@@ -2444,7 +2437,7 @@ converters_from_argtypes(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;
@@ -2473,7 +2466,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;
@@ -2487,7 +2480,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;
         }
@@ -2522,11 +2514,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;
 
@@ -2567,7 +2559,7 @@ PyCFuncPtrType_init(PyObject *self, PyObject *args, PyObject *kwds)
     }
     stginfo->flags |= TYPEFLAG_ISPOINTER;
 
-    if (-1 == make_funcptrtype_dict(attrdict, stginfo)) {
+    if (make_funcptrtype_dict(st, attrdict, stginfo) < 0) {
         Py_DECREF(attrdict);
         return -1;
     }
@@ -2751,9 +2743,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;
 
@@ -2765,7 +2756,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;
@@ -2784,7 +2775,7 @@ PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags)
     }
     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;
     }
@@ -2843,7 +2834,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));
 }
 
@@ -2947,13 +2938,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;
@@ -2969,11 +2960,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);
@@ -2993,7 +2984,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;
 
@@ -3003,7 +2994,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;
@@ -3020,7 +3010,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;
@@ -3032,10 +3022,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;
@@ -3044,27 +3033,28 @@ 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;
@@ -3073,7 +3063,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) {
@@ -3095,7 +3084,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;
@@ -3180,12 +3169,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,
@@ -3193,7 +3182,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;
@@ -3208,10 +3197,17 @@ PyCData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
 /******************************************************************/
 static PyObject *
 GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    ctypes_state *st = GLOBAL_STATE();
+    return generic_pycdata_new(st, type, args, kwds);
+}
+
+static inline PyObject *
+generic_pycdata_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;
@@ -3326,7 +3322,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 = GLOBAL_STATE();
+        converters = converters_from_argtypes(st, ob);
         if (!converters)
             return -1;
         Py_XSETREF(self->converters, converters);
@@ -3422,10 +3419,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;
     }
@@ -3455,12 +3450,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;
@@ -3509,7 +3503,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:
@@ -3641,12 +3635,13 @@ PyCFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds)
         return NULL;
     }
 #endif
-    if (!_validate_paramflags(type, paramflags)) {
+    ctypes_state *st = GLOBAL_STATE();
+    if (!_validate_paramflags(st, type, paramflags)) {
         Py_DECREF(ftuple);
         return NULL;
     }
 
-    self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds);
+    self = (PyCFuncPtrObject *)generic_pycdata_new(st, type, args, kwds);
     if (!self) {
         Py_DECREF(ftuple);
         return NULL;
@@ -3682,10 +3677,11 @@ PyCFuncPtr_FromVtblIndex(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (paramflags == Py_None)
         paramflags = NULL;
 
-    if (!_validate_paramflags(type, paramflags))
+    ctypes_state *st = GLOBAL_STATE();
+    if (!_validate_paramflags(st, type, paramflags)) {
         return NULL;
-
-    self = (PyCFuncPtrObject *)GenericPyCData_new(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))
@@ -3775,14 +3771,15 @@ 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);
     if (!thunk)
         return NULL;
 
-    self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds);
+    self = (PyCFuncPtrObject *)generic_pycdata_new(st, type, args, kwds);
     if (self == NULL) {
         Py_DECREF(thunk);
         return NULL;
@@ -3806,10 +3803,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,
@@ -3817,7 +3813,7 @@ _byref(PyObject *obj)
         return NULL;
     }
 
-    parg = PyCArgObject_new();
+    parg = PyCArgObject_new(st);
     if (parg == NULL) {
         Py_DECREF(obj);
         return NULL;
@@ -3881,7 +3877,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)
 {
@@ -3918,7 +3914,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;
@@ -4156,7 +4151,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");
@@ -4178,7 +4172,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)
@@ -4214,7 +4208,8 @@ PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds)
         }
     }
 
-    result = _ctypes_callproc(pProc,
+    result = _ctypes_callproc(st,
+                       pProc,
                        callargs,
 #ifdef MS_WIN32
                        piunk,
@@ -4536,7 +4531,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);
 }
 
@@ -4682,7 +4677,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);
 }
 
@@ -4789,17 +4784,17 @@ 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);
     if (len == NULL)
@@ -4810,7 +4805,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;
@@ -4829,7 +4824,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,
@@ -4843,7 +4837,7 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length)
         Py_DECREF(key);
         return NULL;
     }
-    if (-1 == PyDict_SetItemProxy(cache, key, result)) {
+    if (PyDict_SetItemProxy(st, st->array_cache, key, result) < 0) {
         Py_DECREF(key);
         Py_DECREF(result);
         return NULL;
@@ -4918,7 +4912,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 = GLOBAL_STATE();
+    if (_ctypes_simple_instance(st, (PyObject *)Py_TYPE(self))) {
         return Py_NewRef(self);
     }
     /* call stginfo->getfunc */
@@ -5015,7 +5010,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);
 }
 
@@ -5059,7 +5054,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);
 }
 
@@ -5079,7 +5074,7 @@ Pointer_get_contents(CDataObject *self, void *closure)
     }
     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);
 }
@@ -5167,7 +5162,7 @@ Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
                         "Cannot create instance: has no _type_");
         return NULL;
     }
-    return GenericPyCData_new(type, args, kw);
+    return generic_pycdata_new(st, type, args, kw);
 }
 
 static PyObject *
@@ -5436,10 +5431,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;
     }
@@ -5468,9 +5461,12 @@ cast_check_pointertype(PyObject *arg)
 static PyObject *
 cast(void *ptr, PyObject *src, PyObject *ctype)
 {
+    ctypes_state *st = GLOBAL_STATE();
+
     CDataObject *result;
-    if (0 == cast_check_pointertype(ctype))
+    if (cast_check_pointertype(st, ctype) == 0) {
         return NULL;
+    }
     result = (CDataObject *)_PyObject_CallNoArgs(ctype);
     if (result == NULL)
         return NULL;
@@ -5481,7 +5477,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;
@@ -5652,10 +5647,10 @@ _ctypes_add_objects(PyObject *mod)
         } \
     } while (0)
 
-    MOD_ADD("_pointer_type_cache", Py_NewRef(_ctypes_ptrtype_cache));
+    ctypes_state *st = GLOBAL_STATE();
+    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 +5680,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 +5690,19 @@ _ctypes_add_objects(PyObject *mod)
 static int
 _ctypes_mod_exec(PyObject *mod)
 {
-    _unpickle = PyObject_GetAttrString(mod, "_unpickle");
-    if (_unpickle == NULL) {
+    ctypes_state *st = GLOBAL_STATE();
+    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;
     }
 
index 08d068e47ee2bfb73b2cacad8873e6698c7d2f02..b6f98e92e1ba88d3bb6e658944d8e2e45ddb3419 100644 (file)
@@ -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) {
@@ -303,8 +303,10 @@ static void closure_fcn(ffi_cif *cif,
                         void *userdata)
 {
     CThunkObject *p = (CThunkObject *)userdata;
+    ctypes_state *st = GLOBAL_STATE();
 
-    _CallPythonObject(resp,
+    _CallPythonObject(st,
+                      resp,
                       p->ffi_restype,
                       p->setfunc,
                       p->callable,
@@ -313,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;
@@ -340,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)
@@ -352,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);
@@ -369,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;
 
index 6ebbb64d61b07a3045ea3318f8b9ec5bc23dab74..67d6ade43a2667ef8784284c4e1d34af9c7bc722 100644 (file)
@@ -153,22 +153,22 @@ 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,8 +188,7 @@ _ctypes_get_errobj(int **pspace)
             PyMem_Free(space);
             return NULL;
         }
-        if (-1 == PyDict_SetItem(dict, error_object_name,
-                                 errobj)) {
+        if (PyDict_SetItem(dict, st->error_object_name, errobj) < 0) {
             Py_DECREF(errobj);
             return NULL;
         }
@@ -202,7 +201,8 @@ static PyObject *
 get_error_internal(PyObject *self, PyObject *args, int index)
 {
     int *space;
-    PyObject *errobj = _ctypes_get_errobj(&space);
+    ctypes_state *st = GLOBAL_STATE();
+    PyObject *errobj = _ctypes_get_errobj(st, &space);
     PyObject *result;
 
     if (errobj == NULL)
@@ -222,7 +222,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 = GLOBAL_STATE();
+    errobj = _ctypes_get_errobj(st, &space);
     if (errobj == NULL)
         return NULL;
     old_errno = space[index];
@@ -473,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;
@@ -662,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);
@@ -677,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;
@@ -748,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;
         }
@@ -783,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;
@@ -825,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,
@@ -926,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;
     }
@@ -993,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;
 
@@ -1004,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;
@@ -1013,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
@@ -1022,9 +1022,10 @@ static PyObject *GetResult(PyObject *restype, void *result, PyObject *checker)
         if (info->getfunc == _ctypes_get_fielddesc("O")->getfunc) {
             Py_DECREF(retval);
         }
-    } else
-        retval = PyCData_FromBaseObj(restype, NULL, 0, result);
-
+    }
+    else {
+        retval = PyCData_FromBaseObj(st, restype, NULL, 0, result);
+    }
     if (!checker || !retval)
         return retval;
 
@@ -1086,7 +1087,7 @@ error:
 #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;
@@ -1138,7 +1139,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);
     }
@@ -1169,7 +1169,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,
@@ -1199,7 +1200,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;
     }
@@ -1232,20 +1233,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 ? */
             }
         }
@@ -1254,7 +1255,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;
@@ -1296,7 +1297,7 @@ PyObject *_ctypes_callproc(PPROC pProc,
             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)))
@@ -1324,7 +1325,7 @@ PyObject *_ctypes_callproc(PPROC pProc,
 #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) {
@@ -1334,7 +1335,7 @@ PyObject *_ctypes_callproc(PPROC pProc,
             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);
@@ -1463,8 +1464,10 @@ 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 = GLOBAL_STATE();
+    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;
 
@@ -1643,7 +1646,9 @@ call_function(PyObject *self, PyObject *args)
         return NULL;
     }
 
-    result =  _ctypes_callproc((PPROC)func,
+    ctypes_state *st = GLOBAL_STATE();
+    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 = GLOBAL_STATE();
+    result = _ctypes_callproc(st,
+                        (PPROC)func,
                         arguments,
 #ifdef MS_WIN32
                         NULL,
@@ -1728,7 +1735,7 @@ PyDoc_STRVAR(alignment_doc,
 static PyObject *
 align_func(PyObject *self, PyObject *obj)
 {
-   ctypes_state *st = GLOBAL_STATE();
+    ctypes_state *st = GLOBAL_STATE();
     StgInfo *info;
     if (PyStgInfo_FromAny(st, obj, &info) < 0) {
         return NULL;
@@ -1774,7 +1781,7 @@ byref(PyObject *self, PyObject *args)
         return NULL;
     }
 
-    parg = PyCArgObject_new();
+    parg = PyCArgObject_new(st);
     if (parg == NULL)
         return NULL;
 
@@ -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 = GLOBAL_STATE();
+    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 (PyDict_SetItem(st->_ctypes_ptrtype_cache, key, result) < 0) {
         Py_DECREF(result);
         Py_DECREF(key);
         return NULL;
@@ -2012,7 +2019,8 @@ 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 = GLOBAL_STATE();
+    if (PyDict_GetItemRef(st->_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg), &typ) < 0) {
         return NULL;
     }
     if (typ == NULL) {
index 16b66382bfe33f5c366c55c98c05fe51de9673b4..ffe00e25aff49f724911e406d3ea82e7868d0518 100644 (file)
@@ -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)
@@ -230,7 +229,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);
 }
 
@@ -248,7 +247,7 @@ PyCField_get(CFieldObject *self, PyObject *inst, PyTypeObject *type)
         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);
 }
 
index d7d725a4fdf669c1f635a51d5d2f90a43624cc9e..3422310045bcc9415e07a3e19a3fee6b6603e3b4 100644 (file)
@@ -42,6 +42,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,7 +59,15 @@ 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;
@@ -73,7 +82,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,
@@ -175,13 +184,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)
@@ -192,11 +201,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);
@@ -306,7 +316,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,
@@ -353,14 +364,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, ...);
@@ -373,10 +385,7 @@ struct basespec {
 
 extern char basespec_string[];
 
-extern ffi_type *_ctypes_get_ffi_type(PyObject *obj);
-
-/* exception classes */
-extern PyObject *PyExc_ArgError;
+extern ffi_type *_ctypes_get_ffi_type(ctypes_state *st, PyObject *obj);
 
 extern char *_ctypes_conversion_encoding;
 extern char *_ctypes_conversion_errors;
@@ -385,16 +394,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);
 
-extern PyObject *_ctypes_ptrtype_cache;
-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);
index 8666ded5c2b3f21cd870e4944cab30bfe2d1fab2..53e7dc39614d210a50d8769592d540c1f92d6cc9 100644 (file)
@@ -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);
index 92fab9b399863680d8aeb164af61cd93dd35c09a..65f94e50e1bd7d30953c68a87771113e5b5a2ef3 100644 (file)
@@ -416,14 +416,14 @@ Modules/xxmodule.c        -       ErrorObject     -
 
 ## manually cached PyUnicodeOjbect
 Modules/_ctypes/callproc.c     _ctypes_get_errobj      error_object_name       -
-Modules/_ctypes/_ctypes.c      CreateSwappedType       suffix  -
+Modules/_ctypes/_ctypes.c      CreateSwappedType       swapped_suffix  -
 
 ##-----------------------
 ## other
 
 ## initialized once
 Modules/_ctypes/_ctypes.c      -       _unpickle       -
-Modules/_ctypes/_ctypes.c      PyCArrayType_from_ctype cache   -
+Modules/_ctypes/_ctypes.c      PyCArrayType_from_ctype array_cache     -
 Modules/_cursesmodule.c        -       ModDict -
 Modules/_datetimemodule.c      datetime_strptime       module  -