gh-117142: ctypes: Migrate global vars to module state (GH-117189)

This commit is contained in:
neonene 2024-03-29 18:40:48 +09:00 committed by GitHub
parent 2e9be80c99
commit 7e2fef8658
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 237 additions and 224 deletions

View file

@ -128,15 +128,6 @@ bytes(cdata)
ctypes_state global_state = {0}; 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 int
PyDict_SetItemProxy(PyObject *dict, PyObject *key, PyObject *item) PyDict_SetItemProxy(ctypes_state *st, PyObject *dict, PyObject *key, PyObject *item)
{ {
PyObject *obj; PyObject *obj;
DictRemoverObject *remover; DictRemoverObject *remover;
PyObject *proxy; PyObject *proxy;
int result; int result;
ctypes_state *st = GLOBAL_STATE();
obj = _PyObject_CallNoArgs((PyObject *)st->DictRemover_Type); obj = _PyObject_CallNoArgs((PyObject *)st->DictRemover_Type);
if (obj == NULL) if (obj == NULL)
return -1; return -1;
@ -562,7 +552,7 @@ static PyType_Spec pyctype_type_spec = {
*/ */
static PyCArgObject * static PyCArgObject *
StructUnionType_paramfunc(CDataObject *self) StructUnionType_paramfunc(ctypes_state *st, CDataObject *self)
{ {
PyCArgObject *parg; PyCArgObject *parg;
PyObject *obj; PyObject *obj;
@ -578,7 +568,6 @@ StructUnionType_paramfunc(CDataObject *self)
/* Create a Python object which calls PyMem_Free(ptr) in /* Create a Python object which calls PyMem_Free(ptr) in
its deallocator. The object will be destroyed its deallocator. The object will be destroyed
at _ctypes_callproc() cleanup. */ at _ctypes_callproc() cleanup. */
ctypes_state *st = GLOBAL_STATE();
PyTypeObject *tp = st->StructParam_Type; PyTypeObject *tp = st->StructParam_Type;
obj = tp->tp_alloc(tp, 0); obj = tp->tp_alloc(tp, 0);
if (obj == NULL) { if (obj == NULL) {
@ -594,13 +583,12 @@ StructUnionType_paramfunc(CDataObject *self)
obj = Py_NewRef(self); obj = Py_NewRef(self);
} }
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) { if (parg == NULL) {
Py_DECREF(obj); Py_DECREF(obj);
return NULL; return NULL;
} }
ctypes_state *st = GLOBAL_STATE();
StgInfo *stginfo; StgInfo *stginfo;
if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) {
Py_DECREF(obj); Py_DECREF(obj);
@ -715,7 +703,8 @@ CDataType_from_address(PyObject *type, PyObject *value)
buf = (void *)PyLong_AsVoidPtr(value); buf = (void *)PyLong_AsVoidPtr(value);
if (PyErr_Occurred()) if (PyErr_Occurred())
return NULL; return NULL;
return PyCData_AtAddress(type, buf); ctypes_state *st = GLOBAL_STATE();
return PyCData_AtAddress(st, type, buf);
} }
PyDoc_STRVAR(from_buffer_doc, PyDoc_STRVAR(from_buffer_doc,
@ -788,7 +777,7 @@ CDataType_from_buffer(PyObject *type, PyObject *args)
return NULL; return NULL;
} }
result = PyCData_AtAddress(type, (char *)buffer->buf + offset); result = PyCData_AtAddress(st, type, (char *)buffer->buf + offset);
if (result == NULL) { if (result == NULL) {
Py_DECREF(mv); Py_DECREF(mv);
return NULL; return NULL;
@ -805,6 +794,10 @@ CDataType_from_buffer(PyObject *type, PyObject *args)
PyDoc_STRVAR(from_buffer_copy_doc, PyDoc_STRVAR(from_buffer_copy_doc,
"C.from_buffer_copy(object, offset=0) -> C instance\ncreate a C instance from a readable buffer"); "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 * static PyObject *
GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds); GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
@ -849,7 +842,7 @@ CDataType_from_buffer_copy(PyObject *type, PyObject *args)
return NULL; return NULL;
} }
result = GenericPyCData_new((PyTypeObject *)type, NULL, NULL); result = generic_pycdata_new(st, (PyTypeObject *)type, NULL, NULL);
if (result != NULL) { if (result != NULL) {
memcpy(((CDataObject *)result)->b_ptr, memcpy(((CDataObject *)result)->b_ptr,
(char *)buffer.buf + offset, info->size); (char *)buffer.buf + offset, info->size);
@ -917,7 +910,8 @@ CDataType_in_dll(PyObject *type, PyObject *args)
return NULL; return NULL;
} }
#endif #endif
return PyCData_AtAddress(type, address); ctypes_state *st = GLOBAL_STATE();
return PyCData_AtAddress(st, type, address);
} }
PyDoc_STRVAR(from_param_doc, PyDoc_STRVAR(from_param_doc,
@ -990,7 +984,8 @@ CDataType_repeat(PyObject *self, Py_ssize_t length)
return PyErr_Format(PyExc_ValueError, return PyErr_Format(PyExc_ValueError,
"Array length must be >= 0, not %zd", "Array length must be >= 0, not %zd",
length); length);
return PyCArrayType_from_ctype(self, length); ctypes_state *st = GLOBAL_STATE();
return PyCArrayType_from_ctype(st, self, length);
} }
static int static int
@ -1106,9 +1101,8 @@ size property/method, and the sequence protocol.
*/ */
static int 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)) { if (!proto || !PyType_Check(proto)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"_type_ must be a type"); "_type_ must be a type");
@ -1129,11 +1123,11 @@ PyCPointerType_SetProto(StgInfo *stginfo, PyObject *proto)
} }
static PyCArgObject * static PyCArgObject *
PyCPointerType_paramfunc(CDataObject *self) PyCPointerType_paramfunc(ctypes_state *st, CDataObject *self)
{ {
PyCArgObject *parg; PyCArgObject *parg;
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) if (parg == NULL)
return NULL; return NULL;
@ -1176,7 +1170,7 @@ PyCPointerType_init(PyObject *self, PyObject *args, PyObject *kwds)
} }
if (proto) { if (proto) {
const char *current_format; const char *current_format;
if (-1 == PyCPointerType_SetProto(stginfo, proto)) { if (PyCPointerType_SetProto(st, stginfo, proto) < 0) {
Py_DECREF(proto); Py_DECREF(proto);
return -1; return -1;
} }
@ -1230,7 +1224,7 @@ PyCPointerType_set_type(PyTypeObject *self, PyObject *type)
return NULL; return NULL;
} }
if (-1 == PyCPointerType_SetProto(info, type)) { if (PyCPointerType_SetProto(st, info, type) < 0) {
Py_DECREF(attrdict); Py_DECREF(attrdict);
return NULL; return NULL;
} }
@ -1244,7 +1238,7 @@ PyCPointerType_set_type(PyTypeObject *self, PyObject *type)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject *_byref(PyObject *); static PyObject *_byref(ctypes_state *, PyObject *);
static PyObject * static PyObject *
PyCPointerType_from_param(PyObject *type, PyObject *value) PyCPointerType_from_param(PyObject *type, PyObject *value)
@ -1272,7 +1266,7 @@ PyCPointerType_from_param(PyObject *type, PyObject *value)
switch (PyObject_IsInstance(value, typeinfo->proto)) { switch (PyObject_IsInstance(value, typeinfo->proto)) {
case 1: case 1:
Py_INCREF(value); /* _byref steals a refcount */ Py_INCREF(value); /* _byref steals a refcount */
return _byref(value); return _byref(st, value);
case -1: case -1:
return NULL; return NULL;
default: default:
@ -1506,9 +1500,9 @@ add_getset(PyTypeObject *type, PyGetSetDef *gsp)
} }
static PyCArgObject * 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) if (p == NULL)
return NULL; return NULL;
p->tag = 'P'; p->tag = 'P';
@ -1684,11 +1678,12 @@ c_wchar_p_from_param(PyObject *type, PyObject *value)
if (value == Py_None) { if (value == Py_None) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
ctypes_state *st = GLOBAL_STATE();
if (PyUnicode_Check(value)) { if (PyUnicode_Check(value)) {
PyCArgObject *parg; PyCArgObject *parg;
struct fielddesc *fd = _ctypes_get_fielddesc("Z"); struct fielddesc *fd = _ctypes_get_fielddesc("Z");
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) if (parg == NULL)
return NULL; return NULL;
parg->pffi_type = &ffi_type_pointer; parg->pffi_type = &ffi_type_pointer;
@ -1706,7 +1701,6 @@ c_wchar_p_from_param(PyObject *type, PyObject *value)
if (res) { if (res) {
return Py_NewRef(value); return Py_NewRef(value);
} }
ctypes_state *st = GLOBAL_STATE();
if (ArrayObject_Check(st, value) || PointerObject_Check(st, value)) { if (ArrayObject_Check(st, value) || PointerObject_Check(st, value)) {
/* c_wchar array instance or pointer(c_wchar(...)) */ /* c_wchar array instance or pointer(c_wchar(...)) */
StgInfo *it; StgInfo *it;
@ -1758,11 +1752,12 @@ c_char_p_from_param(PyObject *type, PyObject *value)
if (value == Py_None) { if (value == Py_None) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
ctypes_state *st = GLOBAL_STATE();
if (PyBytes_Check(value)) { if (PyBytes_Check(value)) {
PyCArgObject *parg; PyCArgObject *parg;
struct fielddesc *fd = _ctypes_get_fielddesc("z"); struct fielddesc *fd = _ctypes_get_fielddesc("z");
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) if (parg == NULL)
return NULL; return NULL;
parg->pffi_type = &ffi_type_pointer; parg->pffi_type = &ffi_type_pointer;
@ -1780,7 +1775,6 @@ c_char_p_from_param(PyObject *type, PyObject *value)
if (res) { if (res) {
return Py_NewRef(value); return Py_NewRef(value);
} }
ctypes_state *st = GLOBAL_STATE();
if (ArrayObject_Check(st, value) || PointerObject_Check(st, value)) { if (ArrayObject_Check(st, value) || PointerObject_Check(st, value)) {
/* c_char array instance or pointer(c_char(...)) */ /* c_char array instance or pointer(c_char(...)) */
StgInfo *it; StgInfo *it;
@ -1834,13 +1828,15 @@ c_void_p_from_param(PyObject *type, PyObject *value)
if (value == Py_None) { if (value == Py_None) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
ctypes_state *st = GLOBAL_STATE();
/* Should probably allow buffer interface as well */ /* Should probably allow buffer interface as well */
/* int, long */ /* int, long */
if (PyLong_Check(value)) { if (PyLong_Check(value)) {
PyCArgObject *parg; PyCArgObject *parg;
struct fielddesc *fd = _ctypes_get_fielddesc("P"); struct fielddesc *fd = _ctypes_get_fielddesc("P");
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) if (parg == NULL)
return NULL; return NULL;
parg->pffi_type = &ffi_type_pointer; parg->pffi_type = &ffi_type_pointer;
@ -1858,7 +1854,7 @@ c_void_p_from_param(PyObject *type, PyObject *value)
PyCArgObject *parg; PyCArgObject *parg;
struct fielddesc *fd = _ctypes_get_fielddesc("z"); struct fielddesc *fd = _ctypes_get_fielddesc("z");
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) if (parg == NULL)
return NULL; return NULL;
parg->pffi_type = &ffi_type_pointer; parg->pffi_type = &ffi_type_pointer;
@ -1875,7 +1871,7 @@ c_void_p_from_param(PyObject *type, PyObject *value)
PyCArgObject *parg; PyCArgObject *parg;
struct fielddesc *fd = _ctypes_get_fielddesc("Z"); struct fielddesc *fd = _ctypes_get_fielddesc("Z");
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) if (parg == NULL)
return NULL; return NULL;
parg->pffi_type = &ffi_type_pointer; parg->pffi_type = &ffi_type_pointer;
@ -1895,7 +1891,6 @@ c_void_p_from_param(PyObject *type, PyObject *value)
/* c_void_p instances */ /* c_void_p instances */
return Py_NewRef(value); return Py_NewRef(value);
} }
ctypes_state *st = GLOBAL_STATE();
/* ctypes array or pointer instance */ /* ctypes array or pointer instance */
if (ArrayObject_Check(st, value) || PointerObject_Check(st, value)) { if (ArrayObject_Check(st, value) || PointerObject_Check(st, value)) {
/* Any array or pointer is accepted */ /* Any array or pointer is accepted */
@ -1914,7 +1909,7 @@ c_void_p_from_param(PyObject *type, PyObject *value)
PyCArgObject *parg; PyCArgObject *parg;
PyCFuncPtrObject *func; PyCFuncPtrObject *func;
func = (PyCFuncPtrObject *)value; func = (PyCFuncPtrObject *)value;
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) if (parg == NULL)
return NULL; return NULL;
parg->pffi_type = &ffi_type_pointer; 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]) { switch (PyUnicode_AsUTF8(stgi->proto)[0]) {
case 'z': /* c_char_p */ case 'z': /* c_char_p */
case 'Z': /* c_wchar_p */ case 'Z': /* c_wchar_p */
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) if (parg == NULL)
return NULL; return NULL;
parg->pffi_type = &ffi_type_pointer; 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_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_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) PyObject *proto, struct fielddesc *fmt)
{ {
PyTypeObject *result; PyTypeObject *result;
PyObject *name = PyTuple_GET_ITEM(args, 0); PyObject *name = PyTuple_GET_ITEM(args, 0);
PyObject *newname; PyObject *newname;
PyObject *swapped_args; PyObject *swapped_args;
static PyObject *suffix;
Py_ssize_t i; Py_ssize_t i;
swapped_args = PyTuple_New(PyTuple_GET_SIZE(args)); swapped_args = PyTuple_New(PyTuple_GET_SIZE(args));
if (!swapped_args) if (!swapped_args)
return NULL; return NULL;
if (suffix == NULL) if (st->swapped_suffix == NULL) {
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
suffix = PyUnicode_InternFromString("_le"); st->swapped_suffix = PyUnicode_InternFromString("_le");
#else #else
suffix = PyUnicode_InternFromString("_be"); st->swapped_suffix = PyUnicode_InternFromString("_be");
#endif #endif
if (suffix == NULL) { }
if (st->swapped_suffix == NULL) {
Py_DECREF(swapped_args); Py_DECREF(swapped_args);
return NULL; return NULL;
} }
newname = PyUnicode_Concat(name, suffix); newname = PyUnicode_Concat(name, st->swapped_suffix);
if (newname == NULL) { if (newname == NULL) {
Py_DECREF(swapped_args); Py_DECREF(swapped_args);
return NULL; return NULL;
@ -2014,8 +2010,6 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject
if (result == NULL) if (result == NULL)
return NULL; return NULL;
ctypes_state *st = GLOBAL_STATE();
StgInfo *stginfo = PyStgInfo_Init(st, result); StgInfo *stginfo = PyStgInfo_Init(st, result);
if (!stginfo) { if (!stginfo) {
Py_DECREF(result); Py_DECREF(result);
@ -2035,13 +2029,12 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject
} }
static PyCArgObject * static PyCArgObject *
PyCSimpleType_paramfunc(CDataObject *self) PyCSimpleType_paramfunc(ctypes_state *st, CDataObject *self)
{ {
const char *fmt; const char *fmt;
PyCArgObject *parg; PyCArgObject *parg;
struct fielddesc *fd; struct fielddesc *fd;
ctypes_state *st = GLOBAL_STATE();
StgInfo *info; StgInfo *info;
if (PyStgInfo_FromObject(st, (PyObject *)self, &info) < 0) { if (PyStgInfo_FromObject(st, (PyObject *)self, &info) < 0) {
return NULL; return NULL;
@ -2053,7 +2046,7 @@ PyCSimpleType_paramfunc(CDataObject *self)
fd = _ctypes_get_fielddesc(fmt); fd = _ctypes_get_fielddesc(fmt);
assert(fd); assert(fd);
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) if (parg == NULL)
return NULL; return NULL;
@ -2198,7 +2191,7 @@ PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds)
&& fmt->setfunc_swapped && fmt->setfunc_swapped
&& fmt->getfunc_swapped) && fmt->getfunc_swapped)
{ {
PyObject *swapped = CreateSwappedType(type, args, kwds, PyObject *swapped = CreateSwappedType(st, type, args, kwds,
proto, fmt); proto, fmt);
if (swapped == NULL) { if (swapped == NULL) {
return -1; return -1;
@ -2272,7 +2265,7 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value)
fd = _ctypes_get_fielddesc(fmt); fd = _ctypes_get_fielddesc(fmt);
assert(fd); assert(fd);
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) if (parg == NULL)
return NULL; return NULL;
@ -2343,7 +2336,7 @@ static PyType_Spec pycsimple_type_spec = {
*/ */
static PyObject * static PyObject *
converters_from_argtypes(PyObject *ob) converters_from_argtypes(ctypes_state *st, PyObject *ob)
{ {
PyObject *converters; PyObject *converters;
Py_ssize_t i; Py_ssize_t i;
@ -2358,7 +2351,7 @@ converters_from_argtypes(PyObject *ob)
Py_ssize_t nArgs = PyTuple_GET_SIZE(ob); Py_ssize_t nArgs = PyTuple_GET_SIZE(ob);
if (nArgs > CTYPES_MAX_ARGCOUNT) { if (nArgs > CTYPES_MAX_ARGCOUNT) {
Py_DECREF(ob); Py_DECREF(ob);
PyErr_Format(PyExc_ArgError, PyErr_Format(st->PyExc_ArgError,
"_argtypes_ has too many arguments (%zi), maximum is %i", "_argtypes_ has too many arguments (%zi), maximum is %i",
nArgs, CTYPES_MAX_ARGCOUNT); nArgs, CTYPES_MAX_ARGCOUNT);
return NULL; return NULL;
@ -2444,7 +2437,7 @@ converters_from_argtypes(PyObject *ob)
} }
static int static int
make_funcptrtype_dict(PyObject *attrdict, StgInfo *stginfo) make_funcptrtype_dict(ctypes_state *st, PyObject *attrdict, StgInfo *stginfo)
{ {
PyObject *ob; PyObject *ob;
PyObject *converters = NULL; PyObject *converters = NULL;
@ -2473,7 +2466,7 @@ make_funcptrtype_dict(PyObject *attrdict, StgInfo *stginfo)
return -1; return -1;
} }
if (ob) { if (ob) {
converters = converters_from_argtypes(ob); converters = converters_from_argtypes(st, ob);
if (!converters) { if (!converters) {
Py_DECREF(ob); Py_DECREF(ob);
return -1; return -1;
@ -2487,7 +2480,6 @@ make_funcptrtype_dict(PyObject *attrdict, StgInfo *stginfo)
} }
if (ob) { if (ob) {
StgInfo *info; StgInfo *info;
ctypes_state *st = GLOBAL_STATE();
if (PyStgInfo_FromType(st, ob, &info) < 0) { if (PyStgInfo_FromType(st, ob, &info) < 0) {
return -1; return -1;
} }
@ -2522,11 +2514,11 @@ make_funcptrtype_dict(PyObject *attrdict, StgInfo *stginfo)
} }
static PyCArgObject * static PyCArgObject *
PyCFuncPtrType_paramfunc(CDataObject *self) PyCFuncPtrType_paramfunc(ctypes_state *st, CDataObject *self)
{ {
PyCArgObject *parg; PyCArgObject *parg;
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) if (parg == NULL)
return NULL; return NULL;
@ -2567,7 +2559,7 @@ PyCFuncPtrType_init(PyObject *self, PyObject *args, PyObject *kwds)
} }
stginfo->flags |= TYPEFLAG_ISPOINTER; stginfo->flags |= TYPEFLAG_ISPOINTER;
if (-1 == make_funcptrtype_dict(attrdict, stginfo)) { if (make_funcptrtype_dict(st, attrdict, stginfo) < 0) {
Py_DECREF(attrdict); Py_DECREF(attrdict);
return -1; return -1;
} }
@ -2751,9 +2743,8 @@ static PyMemberDef PyCData_members[] = {
/* Find the innermost type of an array type, returning a borrowed reference */ /* Find the innermost type of an array type, returning a borrowed reference */
static PyObject * 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)) { if (PyCArrayTypeObject_Check(st, type)) {
PyObject *elem_type; PyObject *elem_type;
@ -2765,7 +2756,7 @@ PyCData_item_type(PyObject *type)
assert(stg_info); assert(stg_info);
elem_type = stg_info->proto; elem_type = stg_info->proto;
assert(elem_type); assert(elem_type);
return PyCData_item_type(elem_type); return PyCData_item_type(st, elem_type);
} }
else { else {
return type; return type;
@ -2784,7 +2775,7 @@ PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags)
} }
assert(info); 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) { if (item_type == NULL) {
return 0; return 0;
} }
@ -2843,7 +2834,7 @@ PyCData_reduce(PyObject *myself, PyObject *args)
if (dict == NULL) { if (dict == NULL) {
return 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)); PyBytes_FromStringAndSize(self->b_ptr, self->b_size));
} }
@ -2947,13 +2938,13 @@ PyCData_MallocBuffer(CDataObject *obj, StgInfo *info)
} }
PyObject * 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; CDataObject *cmem;
assert(PyType_Check(type)); assert(PyType_Check(type));
ctypes_state *st = GLOBAL_STATE();
StgInfo *info; StgInfo *info;
if (PyStgInfo_FromType(st, type, &info) < 0) { if (PyStgInfo_FromType(st, type, &info) < 0) {
return NULL; return NULL;
@ -2969,11 +2960,11 @@ PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr)
if (cmem == NULL) { if (cmem == NULL) {
return NULL; return NULL;
} }
assert(CDataObject_Check(GLOBAL_STATE(), cmem)); assert(CDataObject_Check(st, cmem));
cmem->b_length = info->length; cmem->b_length = info->length;
cmem->b_size = info->size; cmem->b_size = info->size;
if (base) { /* use base's buffer */ if (base) { /* use base's buffer */
assert(CDataObject_Check(GLOBAL_STATE(), base)); assert(CDataObject_Check(st, base));
cmem->b_ptr = adr; cmem->b_ptr = adr;
cmem->b_needsfree = 0; cmem->b_needsfree = 0;
cmem->b_base = (CDataObject *)Py_NewRef(base); 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. Box a memory block into a CData instance.
*/ */
PyObject * PyObject *
PyCData_AtAddress(PyObject *type, void *buf) PyCData_AtAddress(ctypes_state *st, PyObject *type, void *buf)
{ {
CDataObject *pd; CDataObject *pd;
@ -3003,7 +2994,6 @@ PyCData_AtAddress(PyObject *type, void *buf)
assert(PyType_Check(type)); assert(PyType_Check(type));
ctypes_state *st = GLOBAL_STATE();
StgInfo *info; StgInfo *info;
if (PyStgInfo_FromType(st, type, &info) < 0) { if (PyStgInfo_FromType(st, type, &info) < 0) {
return NULL; return NULL;
@ -3020,7 +3010,7 @@ PyCData_AtAddress(PyObject *type, void *buf)
if (!pd) { if (!pd) {
return NULL; return NULL;
} }
assert(CDataObject_Check(GLOBAL_STATE(), pd)); assert(CDataObject_Check(st, pd));
pd->b_ptr = (char *)buf; pd->b_ptr = (char *)buf;
pd->b_length = info->length; pd->b_length = info->length;
pd->b_size = info->size; 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 classes. FALSE otherwise FALSE also for subclasses of c_int and
such. such.
*/ */
int _ctypes_simple_instance(PyObject *obj) int _ctypes_simple_instance(ctypes_state *st, PyObject *obj)
{ {
PyTypeObject *type = (PyTypeObject *)obj; PyTypeObject *type = (PyTypeObject *)obj;
ctypes_state *st = GLOBAL_STATE();
if (PyCSimpleTypeObject_Check(st, type)) { if (PyCSimpleTypeObject_Check(st, type)) {
return type->tp_base != st->Simple_Type; return type->tp_base != st->Simple_Type;
@ -3044,27 +3033,28 @@ int _ctypes_simple_instance(PyObject *obj)
} }
PyObject * 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) Py_ssize_t index, Py_ssize_t size, char *adr)
{ {
if (getfunc) if (getfunc)
return getfunc(adr, size); return getfunc(adr, size);
assert(type); assert(type);
ctypes_state *st = GLOBAL_STATE();
StgInfo *info; StgInfo *info;
if (PyStgInfo_FromType(st, type, &info) < 0) { if (PyStgInfo_FromType(st, type, &info) < 0) {
return NULL; 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 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. Helper function for PyCData_set below.
*/ */
static PyObject * 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) Py_ssize_t size, char *ptr)
{ {
CDataObject *src; CDataObject *src;
@ -3073,7 +3063,6 @@ _PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
if (setfunc) { if (setfunc) {
return setfunc(ptr, value, size); return setfunc(ptr, value, size);
} }
ctypes_state *st = GLOBAL_STATE();
if (!CDataObject_Check(st, value)) { if (!CDataObject_Check(st, value)) {
StgInfo *info; StgInfo *info;
if (PyStgInfo_FromType(st, type, &info) < 0) { 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); ((PyTypeObject *)type)->tp_name);
return NULL; return NULL;
} }
result = _PyCData_set(dst, type, setfunc, ob, result = _PyCData_set(st, dst, type, setfunc, ob,
size, ptr); size, ptr);
Py_DECREF(ob); Py_DECREF(ob);
return result; return result;
@ -3180,12 +3169,12 @@ _PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
* to the value 'value'. * to the value 'value'.
*/ */
int 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) Py_ssize_t index, Py_ssize_t size, char *ptr)
{ {
CDataObject *mem = (CDataObject *)dst; CDataObject *mem = (CDataObject *)dst;
PyObject *result; PyObject *result;
ctypes_state *st = GLOBAL_STATE();
if (!CDataObject_Check(st, dst)) { if (!CDataObject_Check(st, dst)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
@ -3193,7 +3182,7 @@ PyCData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
return -1; return -1;
} }
result = _PyCData_set(mem, type, setfunc, value, result = _PyCData_set(st, mem, type, setfunc, value,
size, ptr); size, ptr);
if (result == NULL) if (result == NULL)
return -1; return -1;
@ -3208,10 +3197,17 @@ PyCData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
/******************************************************************/ /******************************************************************/
static PyObject * static PyObject *
GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 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; CDataObject *obj;
ctypes_state *st = GLOBAL_STATE();
StgInfo *info; StgInfo *info;
if (PyStgInfo_FromType(st, (PyObject *)type, &info) < 0) { if (PyStgInfo_FromType(st, (PyObject *)type, &info) < 0) {
return NULL; return NULL;
@ -3326,7 +3322,8 @@ PyCFuncPtr_set_argtypes(PyCFuncPtrObject *self, PyObject *ob, void *Py_UNUSED(ig
Py_CLEAR(self->converters); Py_CLEAR(self->converters);
Py_CLEAR(self->argtypes); Py_CLEAR(self->argtypes);
} else { } else {
converters = converters_from_argtypes(ob); ctypes_state *st = GLOBAL_STATE();
converters = converters_from_argtypes(st, ob);
if (!converters) if (!converters)
return -1; return -1;
Py_XSETREF(self->converters, converters); 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. */ /* Return 1 if usable, 0 else and exception set. */
static int 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)) { if (PyCPointerTypeObject_Check(st, arg)) {
return 1; return 1;
} }
@ -3455,12 +3450,11 @@ _check_outarg_type(PyObject *arg, Py_ssize_t index)
/* Returns 1 on success, 0 on error */ /* Returns 1 on success, 0 on error */
static int static int
_validate_paramflags(PyTypeObject *type, PyObject *paramflags) _validate_paramflags(ctypes_state *st, PyTypeObject *type, PyObject *paramflags)
{ {
Py_ssize_t i, len; Py_ssize_t i, len;
PyObject *argtypes; PyObject *argtypes;
ctypes_state *st = GLOBAL_STATE();
StgInfo *info; StgInfo *info;
if (PyStgInfo_FromType(st, (PyObject *)type, &info) < 0) { if (PyStgInfo_FromType(st, (PyObject *)type, &info) < 0) {
return -1; return -1;
@ -3509,7 +3503,7 @@ _validate_paramflags(PyTypeObject *type, PyObject *paramflags)
case PARAMFLAG_FIN | PARAMFLAG_FOUT: case PARAMFLAG_FIN | PARAMFLAG_FOUT:
break; break;
case PARAMFLAG_FOUT: case PARAMFLAG_FOUT:
if (!_check_outarg_type(typ, i+1)) if (!_check_outarg_type(st, typ, i+1))
return 0; return 0;
break; break;
default: default:
@ -3641,12 +3635,13 @@ PyCFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL; return NULL;
} }
#endif #endif
if (!_validate_paramflags(type, paramflags)) { ctypes_state *st = GLOBAL_STATE();
if (!_validate_paramflags(st, type, paramflags)) {
Py_DECREF(ftuple); Py_DECREF(ftuple);
return NULL; return NULL;
} }
self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds); self = (PyCFuncPtrObject *)generic_pycdata_new(st, type, args, kwds);
if (!self) { if (!self) {
Py_DECREF(ftuple); Py_DECREF(ftuple);
return NULL; return NULL;
@ -3682,10 +3677,11 @@ PyCFuncPtr_FromVtblIndex(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (paramflags == Py_None) if (paramflags == Py_None)
paramflags = NULL; paramflags = NULL;
if (!_validate_paramflags(type, paramflags)) ctypes_state *st = GLOBAL_STATE();
if (!_validate_paramflags(st, type, paramflags)) {
return NULL; return NULL;
}
self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds); self = (PyCFuncPtrObject *)generic_pycdata_new(st, type, args, kwds);
self->index = index + 0x1000; self->index = index + 0x1000;
self->paramflags = Py_XNewRef(paramflags); self->paramflags = Py_XNewRef(paramflags);
if (iid_len == sizeof(GUID)) if (iid_len == sizeof(GUID))
@ -3775,14 +3771,15 @@ PyCFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL; return NULL;
} }
thunk = _ctypes_alloc_callback(callable, thunk = _ctypes_alloc_callback(st,
callable,
info->argtypes, info->argtypes,
info->restype, info->restype,
info->flags); info->flags);
if (!thunk) if (!thunk)
return NULL; return NULL;
self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds); self = (PyCFuncPtrObject *)generic_pycdata_new(st, type, args, kwds);
if (self == NULL) { if (self == NULL) {
Py_DECREF(thunk); Py_DECREF(thunk);
return NULL; return NULL;
@ -3806,10 +3803,9 @@ PyCFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
_byref consumes a refcount to its argument _byref consumes a refcount to its argument
*/ */
static PyObject * static PyObject *
_byref(PyObject *obj) _byref(ctypes_state *st, PyObject *obj)
{ {
PyCArgObject *parg; PyCArgObject *parg;
ctypes_state *st = GLOBAL_STATE();
if (!CDataObject_Check(st, obj)) { if (!CDataObject_Check(st, obj)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
@ -3817,7 +3813,7 @@ _byref(PyObject *obj)
return NULL; return NULL;
} }
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) { if (parg == NULL) {
Py_DECREF(obj); Py_DECREF(obj);
return NULL; return NULL;
@ -3881,7 +3877,7 @@ _get_arg(int *pindex, PyObject *name, PyObject *defval, PyObject *inargs, PyObje
function. function.
*/ */
static PyObject * static PyObject *
_build_callargs(PyCFuncPtrObject *self, PyObject *argtypes, _build_callargs(ctypes_state *st, PyCFuncPtrObject *self, PyObject *argtypes,
PyObject *inargs, PyObject *kwds, PyObject *inargs, PyObject *kwds,
int *poutmask, int *pinoutmask, unsigned int *pnumretvals) int *poutmask, int *pinoutmask, unsigned int *pnumretvals)
{ {
@ -3918,7 +3914,6 @@ _build_callargs(PyCFuncPtrObject *self, PyObject *argtypes,
inargs_index = 1; inargs_index = 1;
} }
#endif #endif
ctypes_state *st = GLOBAL_STATE();
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
PyObject *item = PyTuple_GET_ITEM(paramflags, i); PyObject *item = PyTuple_GET_ITEM(paramflags, i);
PyObject *ob; PyObject *ob;
@ -4156,7 +4151,6 @@ PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds)
"native com method call without 'this' parameter"); "native com method call without 'this' parameter");
return NULL; return NULL;
} }
ctypes_state *st = GLOBAL_STATE();
if (!CDataObject_Check(st, this)) { if (!CDataObject_Check(st, this)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"Expected a COM this pointer as first argument"); "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]; pProc = ((void **)piunk->lpVtbl)[self->index - 0x1000];
} }
#endif #endif
callargs = _build_callargs(self, argtypes, callargs = _build_callargs(st, self, argtypes,
inargs, kwds, inargs, kwds,
&outmask, &inoutmask, &numretvals); &outmask, &inoutmask, &numretvals);
if (callargs == NULL) 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, callargs,
#ifdef MS_WIN32 #ifdef MS_WIN32
piunk, piunk,
@ -4536,7 +4531,7 @@ Array_item(PyObject *myself, Py_ssize_t index)
size = stginfo->size / stginfo->length; size = stginfo->size / stginfo->length;
offset = index * size; 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); index, size, self->b_ptr + offset);
} }
@ -4682,7 +4677,7 @@ Array_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value)
offset = index * size; offset = index * size;
ptr = self->b_ptr + offset; 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); index, size, ptr);
} }
@ -4789,18 +4784,18 @@ static PyType_Spec pycarray_spec = {
}; };
PyObject * 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; PyObject *key;
char name[256]; char name[256];
PyObject *len; PyObject *len;
if (cache == NULL) { if (st->array_cache == NULL) {
cache = PyDict_New(); st->array_cache = PyDict_New();
if (cache == NULL) if (st->array_cache == NULL) {
return NULL; return NULL;
} }
}
len = PyLong_FromSsize_t(length); len = PyLong_FromSsize_t(length);
if (len == NULL) if (len == NULL)
return NULL; return NULL;
@ -4810,7 +4805,7 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length)
return NULL; return NULL;
PyObject *result; PyObject *result;
if (_PyDict_GetItemProxy(cache, key, &result) != 0) { if (_PyDict_GetItemProxy(st->array_cache, key, &result) != 0) {
// found or error // found or error
Py_DECREF(key); Py_DECREF(key);
return result; return result;
@ -4829,7 +4824,6 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length)
sprintf(name, "%.200s_Array_%ld", sprintf(name, "%.200s_Array_%ld",
((PyTypeObject *)itemtype)->tp_name, (long)length); ((PyTypeObject *)itemtype)->tp_name, (long)length);
#endif #endif
ctypes_state *st = GLOBAL_STATE();
result = PyObject_CallFunction((PyObject *)st->PyCArrayType_Type, result = PyObject_CallFunction((PyObject *)st->PyCArrayType_Type,
"s(O){s:n,s:O}", "s(O){s:n,s:O}",
name, name,
@ -4843,7 +4837,7 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length)
Py_DECREF(key); Py_DECREF(key);
return NULL; return NULL;
} }
if (-1 == PyDict_SetItemProxy(cache, key, result)) { if (PyDict_SetItemProxy(st, st->array_cache, key, result) < 0) {
Py_DECREF(key); Py_DECREF(key);
Py_DECREF(result); Py_DECREF(result);
return NULL; return NULL;
@ -4918,7 +4912,8 @@ static PyGetSetDef Simple_getsets[] = {
static PyObject * static PyObject *
Simple_from_outparm(PyObject *self, PyObject *args) 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); return Py_NewRef(self);
} }
/* call stginfo->getfunc */ /* call stginfo->getfunc */
@ -5015,7 +5010,7 @@ Pointer_item(PyObject *myself, Py_ssize_t index)
size = iteminfo->size; size = iteminfo->size;
offset = index * 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); 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; size = iteminfo->size;
offset = index * 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); 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 */ assert(stginfo); /* Cannot be NULL for pointer instances */
return PyCData_FromBaseObj(stginfo->proto, return PyCData_FromBaseObj(st, stginfo->proto,
(PyObject *)self, 0, (PyObject *)self, 0,
*(void **)self->b_ptr); *(void **)self->b_ptr);
} }
@ -5167,7 +5162,7 @@ Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
"Cannot create instance: has no _type_"); "Cannot create instance: has no _type_");
return NULL; return NULL;
} }
return GenericPyCData_new(type, args, kw); return generic_pycdata_new(st, type, args, kw);
} }
static PyObject * static PyObject *
@ -5436,10 +5431,8 @@ string_at(const char *ptr, int size)
} }
static int 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)) { if (PyCPointerTypeObject_Check(st, arg)) {
return 1; return 1;
} }
@ -5468,9 +5461,12 @@ cast_check_pointertype(PyObject *arg)
static PyObject * static PyObject *
cast(void *ptr, PyObject *src, PyObject *ctype) cast(void *ptr, PyObject *src, PyObject *ctype)
{ {
ctypes_state *st = GLOBAL_STATE();
CDataObject *result; CDataObject *result;
if (0 == cast_check_pointertype(ctype)) if (cast_check_pointertype(st, ctype) == 0) {
return NULL; return NULL;
}
result = (CDataObject *)_PyObject_CallNoArgs(ctype); result = (CDataObject *)_PyObject_CallNoArgs(ctype);
if (result == NULL) if (result == NULL)
return NULL; return NULL;
@ -5481,7 +5477,6 @@ cast(void *ptr, PyObject *src, PyObject *ctype)
It must certainly contain the source objects one. It must certainly contain the source objects one.
It must contain the source object itself. It must contain the source object itself.
*/ */
ctypes_state *st = GLOBAL_STATE();
if (CDataObject_Check(st, src)) { if (CDataObject_Check(st, src)) {
CDataObject *obj = (CDataObject *)src; CDataObject *obj = (CDataObject *)src;
CDataObject *container; CDataObject *container;
@ -5652,10 +5647,10 @@ _ctypes_add_objects(PyObject *mod)
} \ } \
} while (0) } 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 #ifdef MS_WIN32
ctypes_state *st = GLOBAL_STATE();
MOD_ADD("COMError", Py_NewRef(st->PyComError_Type)); MOD_ADD("COMError", Py_NewRef(st->PyComError_Type));
MOD_ADD("FUNCFLAG_HRESULT", PyLong_FromLong(FUNCFLAG_HRESULT)); MOD_ADD("FUNCFLAG_HRESULT", PyLong_FromLong(FUNCFLAG_HRESULT));
MOD_ADD("FUNCFLAG_STDCALL", PyLong_FromLong(FUNCFLAG_STDCALL)); 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_LOCAL", PyLong_FromLong(RTLD_LOCAL));
MOD_ADD("RTLD_GLOBAL", PyLong_FromLong(RTLD_GLOBAL)); MOD_ADD("RTLD_GLOBAL", PyLong_FromLong(RTLD_GLOBAL));
MOD_ADD("CTYPES_MAX_ARGCOUNT", PyLong_FromLong(CTYPES_MAX_ARGCOUNT)); 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)); MOD_ADD("SIZEOF_TIME_T", PyLong_FromSsize_t(SIZEOF_TIME_T));
return 0; return 0;
#undef MOD_ADD #undef MOD_ADD
@ -5695,18 +5690,19 @@ _ctypes_add_objects(PyObject *mod)
static int static int
_ctypes_mod_exec(PyObject *mod) _ctypes_mod_exec(PyObject *mod)
{ {
_unpickle = PyObject_GetAttrString(mod, "_unpickle"); ctypes_state *st = GLOBAL_STATE();
if (_unpickle == NULL) { st->_unpickle = PyObject_GetAttrString(mod, "_unpickle");
if (st->_unpickle == NULL) {
return -1; return -1;
} }
_ctypes_ptrtype_cache = PyDict_New(); st->_ctypes_ptrtype_cache = PyDict_New();
if (_ctypes_ptrtype_cache == NULL) { if (st->_ctypes_ptrtype_cache == NULL) {
return -1; return -1;
} }
PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL); st->PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL);
if (!PyExc_ArgError) { if (!st->PyExc_ArgError) {
return -1; return -1;
} }

View file

@ -136,7 +136,8 @@ TryAddRef(PyObject *cnv, CDataObject *obj)
* Call the python object with all arguments * Call the python object with all arguments
* *
*/ */
static void _CallPythonObject(void *mem, static void _CallPythonObject(ctypes_state *st,
void *mem,
ffi_type *restype, ffi_type *restype,
SETFUNC setfunc, SETFUNC setfunc,
PyObject *callable, PyObject *callable,
@ -155,7 +156,6 @@ static void _CallPythonObject(void *mem,
assert(nargs <= CTYPES_MAX_ARGCOUNT); assert(nargs <= CTYPES_MAX_ARGCOUNT);
PyObject **args = alloca(nargs * sizeof(PyObject *)); PyObject **args = alloca(nargs * sizeof(PyObject *));
PyObject **cnvs = PySequence_Fast_ITEMS(converters); PyObject **cnvs = PySequence_Fast_ITEMS(converters);
ctypes_state *st = GLOBAL_STATE();
for (i = 0; i < nargs; i++) { for (i = 0; i < nargs; i++) {
PyObject *cnv = cnvs[i]; // borrowed ref PyObject *cnv = cnvs[i]; // borrowed ref
@ -164,7 +164,7 @@ static void _CallPythonObject(void *mem,
goto Done; 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); PyObject *v = info->getfunc(*pArgs, info->size);
if (!v) { if (!v) {
PrintError("create argument %zd:\n", i); PrintError("create argument %zd:\n", i);
@ -205,7 +205,7 @@ static void _CallPythonObject(void *mem,
} }
if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) { 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) if (error_object == NULL)
goto Done; goto Done;
if (flags & FUNCFLAG_USE_ERRNO) { if (flags & FUNCFLAG_USE_ERRNO) {
@ -303,8 +303,10 @@ static void closure_fcn(ffi_cif *cif,
void *userdata) void *userdata)
{ {
CThunkObject *p = (CThunkObject *)userdata; CThunkObject *p = (CThunkObject *)userdata;
ctypes_state *st = GLOBAL_STATE();
_CallPythonObject(resp, _CallPythonObject(st,
resp,
p->ffi_restype, p->ffi_restype,
p->setfunc, p->setfunc,
p->callable, p->callable,
@ -313,12 +315,11 @@ static void closure_fcn(ffi_cif *cif,
args); args);
} }
static CThunkObject* CThunkObject_new(Py_ssize_t nargs) static CThunkObject* CThunkObject_new(ctypes_state *st, Py_ssize_t nargs)
{ {
CThunkObject *p; CThunkObject *p;
Py_ssize_t i; Py_ssize_t i;
ctypes_state *st = GLOBAL_STATE();
p = PyObject_GC_NewVar(CThunkObject, st->PyCThunk_Type, nargs); p = PyObject_GC_NewVar(CThunkObject, st->PyCThunk_Type, nargs);
if (p == NULL) { if (p == NULL) {
return NULL; return NULL;
@ -340,7 +341,8 @@ static CThunkObject* CThunkObject_new(Py_ssize_t nargs)
return p; return p;
} }
CThunkObject *_ctypes_alloc_callback(PyObject *callable, CThunkObject *_ctypes_alloc_callback(ctypes_state *st,
PyObject *callable,
PyObject *converters, PyObject *converters,
PyObject *restype, PyObject *restype,
int flags) int flags)
@ -352,11 +354,10 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
assert(PyTuple_Check(converters)); assert(PyTuple_Check(converters));
nargs = PyTuple_GET_SIZE(converters); nargs = PyTuple_GET_SIZE(converters);
p = CThunkObject_new(nargs); p = CThunkObject_new(st, nargs);
if (p == NULL) if (p == NULL)
return NULL; return NULL;
ctypes_state *st = GLOBAL_STATE();
assert(CThunk_CheckExact(st, (PyObject *)p)); assert(CThunk_CheckExact(st, (PyObject *)p));
p->pcl_write = Py_ffi_closure_alloc(sizeof(ffi_closure), &p->pcl_exec); 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); PyObject **cnvs = PySequence_Fast_ITEMS(converters);
for (i = 0; i < nargs; ++i) { for (i = 0; i < nargs; ++i) {
PyObject *cnv = cnvs[i]; // borrowed ref 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; p->atypes[i] = NULL;

View file

@ -153,22 +153,22 @@ static void pymem_destructor(PyObject *ptr)
kept alive in the thread state dictionary as long as the thread itself. kept alive in the thread state dictionary as long as the thread itself.
*/ */
PyObject * PyObject *
_ctypes_get_errobj(int **pspace) _ctypes_get_errobj(ctypes_state *st, int **pspace)
{ {
PyObject *dict = PyThreadState_GetDict(); PyObject *dict = PyThreadState_GetDict();
PyObject *errobj; PyObject *errobj;
static PyObject *error_object_name;
if (dict == NULL) { if (dict == NULL) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
"cannot get thread state"); "cannot get thread state");
return NULL; return NULL;
} }
if (error_object_name == NULL) { if (st->error_object_name == NULL) {
error_object_name = PyUnicode_InternFromString("ctypes.error_object"); st->error_object_name = PyUnicode_InternFromString("ctypes.error_object");
if (error_object_name == NULL) if (st->error_object_name == NULL) {
return NULL; return NULL;
} }
if (PyDict_GetItemRef(dict, error_object_name, &errobj) < 0) { }
if (PyDict_GetItemRef(dict, st->error_object_name, &errobj) < 0) {
return NULL; return NULL;
} }
if (errobj) { if (errobj) {
@ -188,8 +188,7 @@ _ctypes_get_errobj(int **pspace)
PyMem_Free(space); PyMem_Free(space);
return NULL; return NULL;
} }
if (-1 == PyDict_SetItem(dict, error_object_name, if (PyDict_SetItem(dict, st->error_object_name, errobj) < 0) {
errobj)) {
Py_DECREF(errobj); Py_DECREF(errobj);
return NULL; return NULL;
} }
@ -202,7 +201,8 @@ static PyObject *
get_error_internal(PyObject *self, PyObject *args, int index) get_error_internal(PyObject *self, PyObject *args, int index)
{ {
int *space; int *space;
PyObject *errobj = _ctypes_get_errobj(&space); ctypes_state *st = GLOBAL_STATE();
PyObject *errobj = _ctypes_get_errobj(st, &space);
PyObject *result; PyObject *result;
if (errobj == NULL) if (errobj == NULL)
@ -222,7 +222,8 @@ set_error_internal(PyObject *self, PyObject *args, int index)
if (!PyArg_ParseTuple(args, "i", &new_errno)) { if (!PyArg_ParseTuple(args, "i", &new_errno)) {
return NULL; return NULL;
} }
errobj = _ctypes_get_errobj(&space); ctypes_state *st = GLOBAL_STATE();
errobj = _ctypes_get_errobj(st, &space);
if (errobj == NULL) if (errobj == NULL)
return NULL; return NULL;
old_errno = space[index]; old_errno = space[index];
@ -473,10 +474,9 @@ check_hresult(PyObject *self, PyObject *args)
/**************************************************************/ /**************************************************************/
PyCArgObject * PyCArgObject *
PyCArgObject_new(void) PyCArgObject_new(ctypes_state *st)
{ {
PyCArgObject *p; PyCArgObject *p;
ctypes_state *st = GLOBAL_STATE();
p = PyObject_GC_New(PyCArgObject, st->PyCArg_Type); p = PyObject_GC_New(PyCArgObject, st->PyCArg_Type);
if (p == NULL) if (p == NULL)
return NULL; return NULL;
@ -662,10 +662,10 @@ struct argument {
/* /*
* Convert a single Python object into a PyCArgObject and return it. * 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 */ pa->keep = NULL; /* so we cannot forget it later */
ctypes_state *st = GLOBAL_STATE();
StgInfo *info; StgInfo *info;
int result = PyStgInfo_FromObject(st, obj, &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; PyCArgObject *carg;
assert(info->paramfunc); assert(info->paramfunc);
/* If it has an stginfo, it is a CDataObject */ /* If it has an stginfo, it is a CDataObject */
carg = info->paramfunc((CDataObject *)obj); carg = info->paramfunc(st, (CDataObject *)obj);
if (carg == NULL) if (carg == NULL)
return -1; return -1;
pa->ffi_type = carg->pffi_type; pa->ffi_type = carg->pffi_type;
@ -748,7 +748,7 @@ static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa)
*/ */
if (arg) { if (arg) {
int result; int result;
result = ConvParam(arg, index, pa); result = ConvParam(st, arg, index, pa);
Py_DECREF(arg); Py_DECREF(arg);
return result; return result;
} }
@ -783,13 +783,12 @@ int can_return_struct_as_sint64(size_t s)
// returns NULL with exception set on error // 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) { if (obj == NULL) {
return &ffi_type_sint; return &ffi_type_sint;
} }
ctypes_state *st = GLOBAL_STATE();
StgInfo *info; StgInfo *info;
if (PyStgInfo_FromType(st, obj, &info) < 0) { if (PyStgInfo_FromType(st, obj, &info) < 0) {
return NULL; 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); * 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, PPROC pProc,
void **avalues, void **avalues,
ffi_type **atypes, ffi_type **atypes,
@ -926,7 +926,7 @@ static int _call_function_pointer(int flags,
} }
if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) { 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) if (error_object == NULL)
return -1; return -1;
} }
@ -993,7 +993,8 @@ static int _call_function_pointer(int flags,
* - If restype is another ctypes type, return an instance of that. * - If restype is another ctypes type, return an instance of that.
* - Otherwise, call restype and return the result. * - 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; PyObject *retval, *v;
@ -1004,7 +1005,6 @@ static PyObject *GetResult(PyObject *restype, void *result, PyObject *checker)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
ctypes_state *st = GLOBAL_STATE();
StgInfo *info; StgInfo *info;
if (PyStgInfo_FromType(st, restype, &info) < 0) { if (PyStgInfo_FromType(st, restype, &info) < 0) {
return NULL; return NULL;
@ -1013,7 +1013,7 @@ static PyObject *GetResult(PyObject *restype, void *result, PyObject *checker)
return PyObject_CallFunction(restype, "i", *(int *)result); 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); retval = info->getfunc(result, info->size);
/* If restype is py_object (detected by comparing getfunc with /* If restype is py_object (detected by comparing getfunc with
O_get), we have to call Py_DECREF because O_get has already 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) { if (info->getfunc == _ctypes_get_fielddesc("O")->getfunc) {
Py_DECREF(retval); Py_DECREF(retval);
} }
} else }
retval = PyCData_FromBaseObj(restype, NULL, 0, result); else {
retval = PyCData_FromBaseObj(st, restype, NULL, 0, result);
}
if (!checker || !retval) if (!checker || !retval)
return retval; return retval;
@ -1086,7 +1087,7 @@ error:
#ifdef MS_WIN32 #ifdef MS_WIN32
static PyObject * static PyObject *
GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk) GetComError(ctypes_state *st, HRESULT errcode, GUID *riid, IUnknown *pIunk)
{ {
HRESULT hr; HRESULT hr;
ISupportErrorInfo *psei = NULL; ISupportErrorInfo *psei = NULL;
@ -1138,7 +1139,6 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk)
descr, source, helpfile, helpcontext, descr, source, helpfile, helpcontext,
progid); progid);
if (obj) { if (obj) {
ctypes_state *st = GLOBAL_STATE();
PyErr_SetObject((PyObject *)st->PyComError_Type, obj); PyErr_SetObject((PyObject *)st->PyComError_Type, obj);
Py_DECREF(obj); Py_DECREF(obj);
} }
@ -1169,7 +1169,8 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk)
* *
* - XXX various requirements for restype, not yet collected * - XXX various requirements for restype, not yet collected
*/ */
PyObject *_ctypes_callproc(PPROC pProc, PyObject *_ctypes_callproc(ctypes_state *st,
PPROC pProc,
PyObject *argtuple, PyObject *argtuple,
#ifdef MS_WIN32 #ifdef MS_WIN32
IUnknown *pIunk, IUnknown *pIunk,
@ -1199,7 +1200,7 @@ PyObject *_ctypes_callproc(PPROC pProc,
if (argcount > CTYPES_MAX_ARGCOUNT) 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); argcount, CTYPES_MAX_ARGCOUNT);
return NULL; return NULL;
} }
@ -1232,20 +1233,20 @@ PyObject *_ctypes_callproc(PPROC pProc,
converter = PyTuple_GET_ITEM(argtypes, i); converter = PyTuple_GET_ITEM(argtypes, i);
v = PyObject_CallOneArg(converter, arg); v = PyObject_CallOneArg(converter, arg);
if (v == NULL) { if (v == NULL) {
_ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1); _ctypes_extend_error(st->PyExc_ArgError, "argument %zd: ", i+1);
goto cleanup; goto cleanup;
} }
err = ConvParam(v, i+1, pa); err = ConvParam(st, v, i+1, pa);
Py_DECREF(v); Py_DECREF(v);
if (-1 == err) { if (-1 == err) {
_ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1); _ctypes_extend_error(st->PyExc_ArgError, "argument %zd: ", i+1);
goto cleanup; goto cleanup;
} }
} else { } else {
err = ConvParam(arg, i+1, pa); err = ConvParam(st, arg, i+1, pa);
if (-1 == err) { 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 ? */ goto cleanup; /* leaking ? */
} }
} }
@ -1254,7 +1255,7 @@ PyObject *_ctypes_callproc(PPROC pProc,
if (restype == Py_None) { if (restype == Py_None) {
rtype = &ffi_type_void; rtype = &ffi_type_void;
} else { } else {
rtype = _ctypes_get_ffi_type(restype); rtype = _ctypes_get_ffi_type(st, restype);
} }
if (!rtype) { if (!rtype) {
goto cleanup; goto cleanup;
@ -1296,7 +1297,7 @@ PyObject *_ctypes_callproc(PPROC pProc,
avalues[i] = (void *)&args[i].value; 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, rtype, resbuf,
Py_SAFE_DOWNCAST(argcount, Py_ssize_t, int), Py_SAFE_DOWNCAST(argcount, Py_ssize_t, int),
Py_SAFE_DOWNCAST(argtype_count, 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 #ifdef MS_WIN32
if (iid && pIunk) { if (iid && pIunk) {
if (*(int *)resbuf & 0x80000000) if (*(int *)resbuf & 0x80000000)
retval = GetComError(*(HRESULT *)resbuf, iid, pIunk); retval = GetComError(st, *(HRESULT *)resbuf, iid, pIunk);
else else
retval = PyLong_FromLong(*(int *)resbuf); retval = PyLong_FromLong(*(int *)resbuf);
} else if (flags & FUNCFLAG_HRESULT) { } else if (flags & FUNCFLAG_HRESULT) {
@ -1334,7 +1335,7 @@ PyObject *_ctypes_callproc(PPROC pProc,
retval = PyLong_FromLong(*(int *)resbuf); retval = PyLong_FromLong(*(int *)resbuf);
} else } else
#endif #endif
retval = GetResult(restype, resbuf, checker); retval = GetResult(st, restype, resbuf, checker);
cleanup: cleanup:
for (i = 0; i < argcount; ++i) for (i = 0; i < argcount; ++i)
Py_XDECREF(args[i].keep); Py_XDECREF(args[i].keep);
@ -1463,8 +1464,10 @@ copy_com_pointer(PyObject *self, PyObject *args)
return NULL; return NULL;
a.keep = b.keep = 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; goto done;
}
src = (IUnknown *)a.value.p; src = (IUnknown *)a.value.p;
pdst = (IUnknown **)b.value.p; pdst = (IUnknown **)b.value.p;
@ -1643,7 +1646,9 @@ call_function(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
result = _ctypes_callproc((PPROC)func, ctypes_state *st = GLOBAL_STATE();
result = _ctypes_callproc(st,
(PPROC)func,
arguments, arguments,
#ifdef MS_WIN32 #ifdef MS_WIN32
NULL, NULL,
@ -1678,7 +1683,9 @@ call_cdeclfunction(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
result = _ctypes_callproc((PPROC)func, ctypes_state *st = GLOBAL_STATE();
result = _ctypes_callproc(st,
(PPROC)func,
arguments, arguments,
#ifdef MS_WIN32 #ifdef MS_WIN32
NULL, NULL,
@ -1774,7 +1781,7 @@ byref(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
parg = PyCArgObject_new(); parg = PyCArgObject_new(st);
if (parg == NULL) if (parg == NULL)
return NULL; return NULL;
@ -1949,11 +1956,11 @@ create_pointer_type(PyObject *module, PyObject *cls)
PyTypeObject *typ; PyTypeObject *typ;
PyObject *key; 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 // found or error
return result; return result;
} }
ctypes_state *st = GLOBAL_STATE();
// not found // not found
if (PyUnicode_CheckExact(cls)) { if (PyUnicode_CheckExact(cls)) {
PyObject *name = PyUnicode_FromFormat("LP_%U", 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"); PyErr_SetString(PyExc_TypeError, "must be a ctypes type");
return NULL; 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(result);
Py_DECREF(key); Py_DECREF(key);
return NULL; return NULL;
@ -2012,7 +2019,8 @@ create_pointer_inst(PyObject *module, PyObject *arg)
PyObject *result; PyObject *result;
PyObject *typ; 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; return NULL;
} }
if (typ == NULL) { if (typ == NULL) {

View file

@ -44,7 +44,7 @@ static void pymem_destructor(PyObject *ptr)
* prev_desc points to the type of the previous bitfield, if any. * prev_desc points to the type of the previous bitfield, if any.
*/ */
PyObject * 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 *pfield_size, int bitsize, int *pbitofs,
Py_ssize_t *psize, Py_ssize_t *poffset, Py_ssize_t *palign, Py_ssize_t *psize, Py_ssize_t *poffset, Py_ssize_t *palign,
int pack, int big_endian) int pack, int big_endian)
@ -60,7 +60,6 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index,
#define CONT_BITFIELD 2 #define CONT_BITFIELD 2
#define EXPAND_BITFIELD 3 #define EXPAND_BITFIELD 3
ctypes_state *st = GLOBAL_STATE();
PyTypeObject *tp = st->PyCField_Type; PyTypeObject *tp = st->PyCField_Type;
self = (CFieldObject *)tp->tp_alloc(tp, 0); self = (CFieldObject *)tp->tp_alloc(tp, 0);
if (self == NULL) if (self == NULL)
@ -230,7 +229,7 @@ PyCField_set(CFieldObject *self, PyObject *inst, PyObject *value)
"can't delete attribute"); "can't delete attribute");
return -1; 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); self->index, self->size, ptr);
} }
@ -248,7 +247,7 @@ PyCField_get(CFieldObject *self, PyObject *inst, PyTypeObject *type)
return NULL; return NULL;
} }
src = (CDataObject *)inst; 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); self->index, self->size, src->b_ptr + self->offset);
} }

View file

@ -42,6 +42,7 @@ typedef struct {
PyTypeObject *PyCField_Type; PyTypeObject *PyCField_Type;
PyTypeObject *PyCThunk_Type; PyTypeObject *PyCThunk_Type;
PyTypeObject *StructParam_Type; PyTypeObject *StructParam_Type;
PyTypeObject *PyCType_Type;
PyTypeObject *PyCStructType_Type; PyTypeObject *PyCStructType_Type;
PyTypeObject *UnionType_Type; PyTypeObject *UnionType_Type;
PyTypeObject *PyCPointerType_Type; PyTypeObject *PyCPointerType_Type;
@ -58,7 +59,15 @@ typedef struct {
#ifdef MS_WIN32 #ifdef MS_WIN32
PyTypeObject *PyComError_Type; PyTypeObject *PyComError_Type;
#endif #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; } ctypes_state;
extern ctypes_state global_state; extern ctypes_state global_state;
@ -73,7 +82,7 @@ typedef struct tagPyCArgObject PyCArgObject;
typedef struct tagCDataObject CDataObject; typedef struct tagCDataObject CDataObject;
typedef PyObject *(* GETFUNC)(void *, Py_ssize_t size); typedef PyObject *(* GETFUNC)(void *, Py_ssize_t size);
typedef PyObject *(* SETFUNC)(void *, PyObject *value, 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 /* 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, 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 * 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 *pfield_size, int bitsize, int *pbitofs,
Py_ssize_t *psize, Py_ssize_t *poffset, Py_ssize_t *palign, Py_ssize_t *psize, Py_ssize_t *poffset, Py_ssize_t *palign,
int pack, int is_big_endian); int pack, int is_big_endian);
extern PyObject *PyCData_AtAddress(PyObject *type, void *buf); extern PyObject *PyCData_AtAddress(ctypes_state *st, PyObject *type, void *buf);
extern PyObject *PyCData_FromBytes(PyObject *type, char *data, Py_ssize_t length); 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 PyCArrayTypeObject_Check(st, v) PyObject_TypeCheck((v), (st)->PyCArrayType_Type)
#define ArrayObject_Check(st, v) PyObject_TypeCheck((v), (st)->PyCArray_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) #define PyCStructTypeObject_Check(st, v) PyObject_TypeCheck((v), (st)->PyCStructType_Type)
extern PyObject * 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 PyMethodDef _ctypes_module_methods[];
extern CThunkObject *_ctypes_alloc_callback(PyObject *callable, extern CThunkObject *_ctypes_alloc_callback(ctypes_state *st,
PyObject *callable,
PyObject *converters, PyObject *converters,
PyObject *restype, PyObject *restype,
int flags); int flags);
@ -306,7 +316,8 @@ extern int PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info);
typedef int(* PPROC)(void); typedef int(* PPROC)(void);
PyObject *_ctypes_callproc(PPROC pProc, PyObject *_ctypes_callproc(ctypes_state *st,
PPROC pProc,
PyObject *arguments, PyObject *arguments,
#ifdef MS_WIN32 #ifdef MS_WIN32
IUnknown *pIUnk, IUnknown *pIUnk,
@ -353,14 +364,15 @@ struct tagPyCArgObject {
}; };
#define PyCArg_CheckExact(st, v) Py_IS_TYPE(v, st->PyCArg_Type) #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 * 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); Py_ssize_t index, Py_ssize_t size, char *ptr);
extern int 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); Py_ssize_t index, Py_ssize_t size, char *ptr);
extern void _ctypes_extend_error(PyObject *exc_class, const char *fmt, ...); extern void _ctypes_extend_error(PyObject *exc_class, const char *fmt, ...);
@ -373,10 +385,7 @@ struct basespec {
extern char basespec_string[]; 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);
/* exception classes */
extern PyObject *PyExc_ArgError;
extern char *_ctypes_conversion_encoding; extern char *_ctypes_conversion_encoding;
extern char *_ctypes_conversion_errors; extern char *_ctypes_conversion_errors;
@ -385,16 +394,16 @@ extern char *_ctypes_conversion_errors;
extern void _ctypes_free_closure(void *); extern void _ctypes_free_closure(void *);
extern void *_ctypes_alloc_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(const char *prefix, const char *suffix);
extern char *_ctypes_alloc_format_string_with_shape(int ndim, extern char *_ctypes_alloc_format_string_with_shape(int ndim,
const Py_ssize_t *shape, const Py_ssize_t *shape,
const char *prefix, const char *suffix); 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(ctypes_state *st, int **pspace);
PyObject *_ctypes_get_errobj(int **pspace);
#ifdef USING_MALLOC_CLOSURE_DOT_C #ifdef USING_MALLOC_CLOSURE_DOT_C
void Py_ffi_closure_free(void *p); void Py_ffi_closure_free(void *p);

View file

@ -488,7 +488,7 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct
/* construct the field now, as `prop->offset` is `offset` with /* construct the field now, as `prop->offset` is `offset` with
corrected alignment */ corrected alignment */
prop = PyCField_FromDesc(desc, i, prop = PyCField_FromDesc(st, desc, i,
&field_size, bitsize, &bitofs, &field_size, bitsize, &bitofs,
&size, &offset, &align, &size, &offset, &align,
pack, big_endian); pack, big_endian);
@ -542,7 +542,7 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct
size = 0; size = 0;
offset = 0; offset = 0;
align = 0; align = 0;
prop = PyCField_FromDesc(desc, i, prop = PyCField_FromDesc(st, desc, i,
&field_size, bitsize, &bitofs, &field_size, bitsize, &bitofs,
&size, &offset, &align, &size, &offset, &align,
pack, big_endian); pack, big_endian);

View file

@ -416,14 +416,14 @@ Modules/xxmodule.c - ErrorObject -
## manually cached PyUnicodeOjbect ## manually cached PyUnicodeOjbect
Modules/_ctypes/callproc.c _ctypes_get_errobj error_object_name - Modules/_ctypes/callproc.c _ctypes_get_errobj error_object_name -
Modules/_ctypes/_ctypes.c CreateSwappedType suffix - Modules/_ctypes/_ctypes.c CreateSwappedType swapped_suffix -
##----------------------- ##-----------------------
## other ## other
## initialized once ## initialized once
Modules/_ctypes/_ctypes.c - _unpickle - 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/_cursesmodule.c - ModDict -
Modules/_datetimemodule.c datetime_strptime module - Modules/_datetimemodule.c datetime_strptime module -

Can't render this file because it has a wrong number of fields in line 4.