Skip to content

gh-114314: Move types to ctypes_state #114316

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 58 additions & 38 deletions Modules/_ctypes/_ctypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,8 @@ PyCPointerType_from_param(PyObject *type, PyObject *value)
break;
}

if (PointerObject_Check(value) || ArrayObject_Check(value)) {
ctypes_state *state = GLOBAL_STATE();
if (PointerObject_Check(state, value) || ArrayObject_Check(state, value)) {
/* Array instances are also pointers when
the item types are the same.
*/
Expand Down Expand Up @@ -1587,7 +1588,8 @@ c_wchar_p_from_param(PyObject *type, PyObject *value)
if (res) {
return Py_NewRef(value);
}
if (ArrayObject_Check(value) || PointerObject_Check(value)) {
ctypes_state *state = GLOBAL_STATE();
if (ArrayObject_Check(state, value) || PointerObject_Check(state, value)) {
/* c_wchar array instance or pointer(c_wchar(...)) */
StgDictObject *dt = PyObject_stgdict(value);
StgDictObject *dict;
Expand Down Expand Up @@ -1651,7 +1653,8 @@ c_char_p_from_param(PyObject *type, PyObject *value)
if (res) {
return Py_NewRef(value);
}
if (ArrayObject_Check(value) || PointerObject_Check(value)) {
ctypes_state *state = GLOBAL_STATE();
if (ArrayObject_Check(state, value) || PointerObject_Check(state, value)) {
/* c_char array instance or pointer(c_char(...)) */
StgDictObject *dt = PyObject_stgdict(value);
StgDictObject *dict;
Expand Down Expand Up @@ -1758,21 +1761,21 @@ c_void_p_from_param(PyObject *type, PyObject *value)
return Py_NewRef(value);
}
/* ctypes array or pointer instance */
if (ArrayObject_Check(value) || PointerObject_Check(value)) {
ctypes_state *state = GLOBAL_STATE();
if (ArrayObject_Check(state, value) || PointerObject_Check(state, value)) {
/* Any array or pointer is accepted */
return Py_NewRef(value);
}
/* byref(...) */
ctypes_state *st = GLOBAL_STATE();
if (PyCArg_CheckExact(st, value)) {
if (PyCArg_CheckExact(state, value)) {
/* byref(c_xxx()) */
PyCArgObject *a = (PyCArgObject *)value;
if (a->tag == 'P') {
return Py_NewRef(value);
}
}
/* function pointer */
if (PyCFuncPtrObject_Check(value)) {
if (PyCFuncPtrObject_Check(state, value)) {
PyCArgObject *parg;
PyCFuncPtrObject *func;
func = (PyCFuncPtrObject *)value;
Expand All @@ -1788,7 +1791,7 @@ c_void_p_from_param(PyObject *type, PyObject *value)
}
/* c_char_p, c_wchar_p */
stgd = PyObject_stgdict(value);
if (stgd && CDataObject_Check(value) && stgd->proto && PyUnicode_Check(stgd->proto)) {
if (stgd && CDataObject_Check(state, value) && stgd->proto && PyUnicode_Check(stgd->proto)) {
PyCArgObject *parg;

switch (PyUnicode_AsUTF8(stgd->proto)[0]) {
Expand Down Expand Up @@ -2006,7 +2009,7 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)

stgdict->paramfunc = PyCSimpleType_paramfunc;
/*
if (result->tp_base != &Simple_Type) {
if (result->tp_base != state->Simple_Type) {
stgdict->setfunc = NULL;
stgdict->getfunc = NULL;
}
Expand All @@ -2026,7 +2029,8 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
/* Install from_param class methods in ctypes base classes.
Overrides the PyCSimpleType_from_param generic method.
*/
if (result->tp_base == &Simple_Type) {
ctypes_state *state = GLOBAL_STATE();
if (result->tp_base == state->Simple_Type) {
switch (*proto_str) {
case 'z': /* c_char_p */
ml = &c_char_p_method;
Expand Down Expand Up @@ -2834,12 +2838,13 @@ PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr)
cmem = (CDataObject *)((PyTypeObject *)type)->tp_alloc((PyTypeObject *)type, 0);
if (cmem == NULL)
return NULL;
assert(CDataObject_Check(cmem));
ctypes_state *state = GLOBAL_STATE();
assert(CDataObject_Check(state, cmem));

cmem->b_length = dict->length;
cmem->b_size = dict->size;
if (base) { /* use base's buffer */
assert(CDataObject_Check(base));
assert(CDataObject_Check(state, base));
cmem->b_ptr = adr;
cmem->b_needsfree = 0;
cmem->b_base = (CDataObject *)Py_NewRef(base);
Expand Down Expand Up @@ -2880,7 +2885,8 @@ PyCData_AtAddress(PyObject *type, void *buf)
pd = (CDataObject *)((PyTypeObject *)type)->tp_alloc((PyTypeObject *)type, 0);
if (!pd)
return NULL;
assert(CDataObject_Check(pd));
ctypes_state *state = GLOBAL_STATE();
assert(CDataObject_Check(state, pd));
pd->b_ptr = (char *)buf;
pd->b_length = dict->length;
pd->b_size = dict->size;
Expand All @@ -2896,8 +2902,10 @@ int _ctypes_simple_instance(PyObject *obj)
{
PyTypeObject *type = (PyTypeObject *)obj;

if (PyCSimpleTypeObject_Check(type))
return type->tp_base != &Simple_Type;
if (PyCSimpleTypeObject_Check(type)) {
ctypes_state *state = GLOBAL_STATE();
return type->tp_base != state->Simple_Type;
}
return 0;
}

Expand All @@ -2919,16 +2927,17 @@ PyCData_get(PyObject *type, GETFUNC getfunc, PyObject *src,
Helper function for PyCData_set below.
*/
static PyObject *
_PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
Py_ssize_t size, char *ptr)
_PyCData_set(ctypes_state *state, CDataObject *dst, PyObject *type,
SETFUNC setfunc, PyObject *value,
Py_ssize_t size, char *ptr)
{
CDataObject *src;
int err;

if (setfunc)
return setfunc(ptr, value, size);

if (!CDataObject_Check(value)) {
if (!CDataObject_Check(state, value)) {
StgDictObject *dict = PyType_stgdict(type);
if (dict && dict->setfunc)
return dict->setfunc(ptr, value, size);
Expand All @@ -2946,8 +2955,8 @@ _PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
((PyTypeObject *)type)->tp_name);
return NULL;
}
result = _PyCData_set(dst, type, setfunc, ob,
size, ptr);
result = _PyCData_set(state, dst, type, setfunc, ob,
size, ptr);
Py_DECREF(ob);
return result;
} else if (value == Py_None && PyCPointerTypeObject_Check(type)) {
Expand Down Expand Up @@ -2983,7 +2992,7 @@ _PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
}

if (PyCPointerTypeObject_Check(type)
&& ArrayObject_Check(value)) {
&& ArrayObject_Check(state, value)) {
StgDictObject *p1, *p2;
PyObject *keep;
p1 = PyObject_stgdict(value);
Expand Down Expand Up @@ -3032,14 +3041,15 @@ PyCData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
CDataObject *mem = (CDataObject *)dst;
PyObject *result;

if (!CDataObject_Check(dst)) {
ctypes_state *state = GLOBAL_STATE();
if (!CDataObject_Check(state, dst)) {
PyErr_SetString(PyExc_TypeError,
"not a ctype instance");
return -1;
}

result = _PyCData_set(mem, type, setfunc, value,
size, ptr);
result = _PyCData_set(state, mem, type, setfunc, value,
size, ptr);
if (result == NULL)
return -1;

Expand Down Expand Up @@ -3627,7 +3637,8 @@ static PyObject *
_byref(PyObject *obj)
{
PyCArgObject *parg;
if (!CDataObject_Check(obj)) {
ctypes_state *state = GLOBAL_STATE();
if (!CDataObject_Check(state, obj)) {
PyErr_SetString(PyExc_TypeError,
"expected CData instance");
return NULL;
Expand Down Expand Up @@ -3962,7 +3973,8 @@ PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds)
"native com method call without 'this' parameter");
return NULL;
}
if (!CDataObject_Check(this)) {
ctypes_state *state = GLOBAL_STATE();
if (!CDataObject_Check(state, this)) {
PyErr_SetString(PyExc_TypeError,
"Expected a COM this pointer as first argument");
return NULL;
Expand Down Expand Up @@ -4734,11 +4746,11 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length)
((PyTypeObject *)itemtype)->tp_name, (long)length);
#endif

ctypes_state *st = GLOBAL_STATE();
result = PyObject_CallFunction((PyObject *)st->PyCArrayType_Type,
ctypes_state *state = GLOBAL_STATE();
result = PyObject_CallFunction((PyObject *)state->PyCArrayType_Type,
"s(O){s:n,s:O}",
name,
&PyCArray_Type,
state->PyCArray_Type,
"_length_",
length,
"_type_",
Expand Down Expand Up @@ -4850,7 +4862,8 @@ Simple_repr(CDataObject *self)
{
PyObject *val, *result;

if (Py_TYPE(self)->tp_base != &Simple_Type) {
ctypes_state *state = GLOBAL_STATE();
if (Py_TYPE(self)->tp_base != state->Simple_Type) {
return PyUnicode_FromFormat("<%s object at %p>",
Py_TYPE(self)->tp_name, self);
}
Expand Down Expand Up @@ -5013,7 +5026,8 @@ Pointer_set_contents(CDataObject *self, PyObject *value, void *closure)
stgdict = PyObject_stgdict((PyObject *)self);
assert(stgdict); /* Cannot be NULL for pointer instances */
assert(stgdict->proto);
if (!CDataObject_Check(value)) {
ctypes_state *state = GLOBAL_STATE();
if (!CDataObject_Check(state, value)) {
int res = PyObject_IsInstance(value, stgdict->proto);
if (res == -1)
return -1;
Expand Down Expand Up @@ -5432,7 +5446,8 @@ cast(void *ptr, PyObject *src, PyObject *ctype)
It must certainly contain the source objects one.
It must contain the source object itself.
*/
if (CDataObject_Check(src)) {
ctypes_state *state = GLOBAL_STATE();
if (CDataObject_Check(state, src)) {
CDataObject *obj = (CDataObject *)src;
CDataObject *container;

Expand Down Expand Up @@ -5537,6 +5552,8 @@ _ctypes_add_types(PyObject *mod)
CREATE_TYPE(mod, st->PyCArg_Type, &carg_spec, NULL);
CREATE_TYPE(mod, st->PyCThunk_Type, &cthunk_spec, NULL);
TYPE_READY(&PyCData_Type);
st->PyCData_Type = &PyCData_Type;

/* StgDict is derived from PyDict_Type */
TYPE_READY_BASE(&PyCStgDict_Type, &PyDict_Type);

Expand All @@ -5561,12 +5578,15 @@ _ctypes_add_types(PyObject *mod)
* Classes using a custom metaclass
*/

MOD_ADD_TYPE(&Struct_Type, st->PyCStructType_Type, &PyCData_Type);
MOD_ADD_TYPE(&Union_Type, st->UnionType_Type, &PyCData_Type);
MOD_ADD_TYPE(&PyCPointer_Type, st->PyCPointerType_Type, &PyCData_Type);
MOD_ADD_TYPE(&PyCArray_Type, st->PyCArrayType_Type, &PyCData_Type);
MOD_ADD_TYPE(&Simple_Type, st->PyCSimpleType_Type, &PyCData_Type);
MOD_ADD_TYPE(&PyCFuncPtr_Type, st->PyCFuncPtrType_Type, &PyCData_Type);
MOD_ADD_TYPE(&Struct_Type, st->PyCStructType_Type, st->PyCData_Type);
MOD_ADD_TYPE(&Union_Type, st->UnionType_Type, st->PyCData_Type);
MOD_ADD_TYPE(&PyCPointer_Type, st->PyCPointerType_Type, st->PyCData_Type);
st->PyCPointer_Type = &PyCPointer_Type;
MOD_ADD_TYPE(&PyCArray_Type, st->PyCArrayType_Type, st->PyCData_Type);
st->PyCArray_Type = &PyCArray_Type;
MOD_ADD_TYPE(&Simple_Type, st->PyCSimpleType_Type, st->PyCData_Type);
st->Simple_Type = &Simple_Type;
MOD_ADD_TYPE(&PyCFuncPtr_Type, st->PyCFuncPtrType_Type, st->PyCData_Type);

/*************************************************
*
Expand Down
7 changes: 4 additions & 3 deletions Modules/_ctypes/callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ static void _CallPythonObject(void *mem,
Py_ssize_t i = 0, j = 0, nargs = 0;
PyObject *error_object = NULL;
int *space;
PyGILState_STATE state = PyGILState_Ensure();
PyGILState_STATE gil_state = PyGILState_Ensure();
ctypes_state *state = GLOBAL_STATE();

assert(PyTuple_Check(converters));
nargs = PyTuple_GET_SIZE(converters);
Expand Down Expand Up @@ -175,7 +176,7 @@ static void _CallPythonObject(void *mem,
PrintError("create argument %zd:\n", i);
goto Done;
}
if (!CDataObject_Check(obj)) {
if (!CDataObject_Check(state, obj)) {
Py_DECREF(obj);
PrintError("unexpected result of create argument %zd:\n", i);
goto Done;
Expand Down Expand Up @@ -285,7 +286,7 @@ static void _CallPythonObject(void *mem,
for (j = 0; j < i; j++) {
Py_DECREF(args[j]);
}
PyGILState_Release(state);
PyGILState_Release(gil_state);
}

static void closure_fcn(ffi_cif *cif,
Expand Down
20 changes: 13 additions & 7 deletions Modules/_ctypes/callproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1689,8 +1689,10 @@ sizeof_func(PyObject *self, PyObject *obj)
if (dict)
return PyLong_FromSsize_t(dict->size);

if (CDataObject_Check(obj))
ctypes_state *state = GLOBAL_STATE();
if (CDataObject_Check(state, obj)) {
return PyLong_FromSsize_t(((CDataObject *)obj)->b_size);
}
PyErr_SetString(PyExc_TypeError,
"this type has no size");
return NULL;
Expand Down Expand Up @@ -1744,7 +1746,8 @@ byref(PyObject *self, PyObject *args)
if (offset == -1 && PyErr_Occurred())
return NULL;
}
if (!CDataObject_Check(obj)) {
ctypes_state *state = GLOBAL_STATE();
if (!CDataObject_Check(state, obj)) {
PyErr_Format(PyExc_TypeError,
"byref() argument must be a ctypes instance, not '%s'",
Py_TYPE(obj)->tp_name);
Expand All @@ -1769,7 +1772,8 @@ PyDoc_STRVAR(addressof_doc,
static PyObject *
addressof(PyObject *self, PyObject *obj)
{
if (!CDataObject_Check(obj)) {
ctypes_state *state = GLOBAL_STATE();
if (!CDataObject_Check(state, obj)) {
PyErr_SetString(PyExc_TypeError,
"invalid type");
return NULL;
Expand Down Expand Up @@ -1925,13 +1929,15 @@ create_pointer_type(PyObject *module, PyObject *cls)
// found or error
return result;
}

// not found
ctypes_state *state = GLOBAL_STATE();
if (PyUnicode_CheckExact(cls)) {
PyObject *name = PyUnicode_FromFormat("LP_%U", cls);
result = PyObject_CallFunction((PyObject *)Py_TYPE(&PyCPointer_Type),
result = PyObject_CallFunction((PyObject *)Py_TYPE(state->PyCPointer_Type),
"N(O){}",
name,
&PyCPointer_Type);
state->PyCPointer_Type);
if (result == NULL)
return result;
key = PyLong_FromVoidPtr(result);
Expand All @@ -1942,10 +1948,10 @@ create_pointer_type(PyObject *module, PyObject *cls)
} else if (PyType_Check(cls)) {
typ = (PyTypeObject *)cls;
PyObject *name = PyUnicode_FromFormat("LP_%s", typ->tp_name);
result = PyObject_CallFunction((PyObject *)Py_TYPE(&PyCPointer_Type),
result = PyObject_CallFunction((PyObject *)Py_TYPE(state->PyCPointer_Type),
"N(O){sO}",
name,
&PyCPointer_Type,
state->PyCPointer_Type,
"_type_", cls);
if (result == NULL)
return result;
Expand Down
6 changes: 4 additions & 2 deletions Modules/_ctypes/cfield.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ PyCField_set(CFieldObject *self, PyObject *inst, PyObject *value)
{
CDataObject *dst;
char *ptr;
if (!CDataObject_Check(inst)) {
ctypes_state *state = GLOBAL_STATE();
if (!CDataObject_Check(state, inst)) {
PyErr_SetString(PyExc_TypeError,
"not a ctype instance");
return -1;
Expand All @@ -227,7 +228,8 @@ PyCField_get(CFieldObject *self, PyObject *inst, PyTypeObject *type)
if (inst == NULL) {
return Py_NewRef(self);
}
if (!CDataObject_Check(inst)) {
ctypes_state *state = GLOBAL_STATE();
if (!CDataObject_Check(state, inst)) {
PyErr_SetString(PyExc_TypeError,
"not a ctype instance");
return NULL;
Expand Down
Loading