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;
-
/****************************************************************/
};
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;
*/
static PyCArgObject *
-StructUnionType_paramfunc(CDataObject *self)
+StructUnionType_paramfunc(ctypes_state *st, CDataObject *self)
{
PyCArgObject *parg;
PyObject *obj;
/* 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) {
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);
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,
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;
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);
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);
return NULL;
}
#endif
- return PyCData_AtAddress(type, address);
+ ctypes_state *st = GLOBAL_STATE();
+ return PyCData_AtAddress(st, type, address);
}
PyDoc_STRVAR(from_param_doc,
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
*/
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");
}
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;
}
if (proto) {
const char *current_format;
- if (-1 == PyCPointerType_SetProto(stginfo, proto)) {
+ if (PyCPointerType_SetProto(st, stginfo, proto) < 0) {
Py_DECREF(proto);
return -1;
}
return NULL;
}
- if (-1 == PyCPointerType_SetProto(info, type)) {
+ if (PyCPointerType_SetProto(st, info, type) < 0) {
Py_DECREF(attrdict);
return NULL;
}
Py_RETURN_NONE;
}
-static PyObject *_byref(PyObject *);
+static PyObject *_byref(ctypes_state *, PyObject *);
static PyObject *
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:
}
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';
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;
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;
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;
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;
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;
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;
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;
/* 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 */
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;
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;
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;
if (result == NULL)
return NULL;
- ctypes_state *st = GLOBAL_STATE();
-
StgInfo *stginfo = PyStgInfo_Init(st, result);
if (!stginfo) {
Py_DECREF(result);
}
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;
fd = _ctypes_get_fielddesc(fmt);
assert(fd);
- parg = PyCArgObject_new();
+ parg = PyCArgObject_new(st);
if (parg == NULL)
return NULL;
&& 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;
fd = _ctypes_get_fielddesc(fmt);
assert(fd);
- parg = PyCArgObject_new();
+ parg = PyCArgObject_new(st);
if (parg == NULL)
return NULL;
*/
static PyObject *
-converters_from_argtypes(PyObject *ob)
+converters_from_argtypes(ctypes_state *st, PyObject *ob)
{
PyObject *converters;
Py_ssize_t i;
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;
}
static int
-make_funcptrtype_dict(PyObject *attrdict, StgInfo *stginfo)
+make_funcptrtype_dict(ctypes_state *st, PyObject *attrdict, StgInfo *stginfo)
{
PyObject *ob;
PyObject *converters = NULL;
return -1;
}
if (ob) {
- converters = converters_from_argtypes(ob);
+ converters = converters_from_argtypes(st, ob);
if (!converters) {
Py_DECREF(ob);
return -1;
}
if (ob) {
StgInfo *info;
- ctypes_state *st = GLOBAL_STATE();
if (PyStgInfo_FromType(st, ob, &info) < 0) {
return -1;
}
}
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;
}
stginfo->flags |= TYPEFLAG_ISPOINTER;
- if (-1 == make_funcptrtype_dict(attrdict, stginfo)) {
+ if (make_funcptrtype_dict(st, attrdict, stginfo) < 0) {
Py_DECREF(attrdict);
return -1;
}
/* 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;
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;
}
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;
}
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));
}
}
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;
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);
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;
assert(PyType_Check(type));
- ctypes_state *st = GLOBAL_STATE();
StgInfo *info;
if (PyStgInfo_FromType(st, type, &info) < 0) {
return NULL;
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;
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;
}
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;
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) {
((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;
* 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,
return -1;
}
- result = _PyCData_set(mem, type, setfunc, value,
+ result = _PyCData_set(st, mem, type, setfunc, value,
size, ptr);
if (result == NULL)
return -1;
/******************************************************************/
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;
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);
/* 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;
}
/* 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;
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:
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;
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))
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;
_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,
return NULL;
}
- parg = PyCArgObject_new();
+ parg = PyCArgObject_new(st);
if (parg == NULL) {
Py_DECREF(obj);
return NULL;
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)
{
inargs_index = 1;
}
#endif
- ctypes_state *st = GLOBAL_STATE();
for (i = 0; i < len; ++i) {
PyObject *item = PyTuple_GET_ITEM(paramflags, i);
PyObject *ob;
"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");
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)
}
}
- result = _ctypes_callproc(pProc,
+ result = _ctypes_callproc(st,
+ pProc,
callargs,
#ifdef MS_WIN32
piunk,
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);
}
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);
}
};
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)
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;
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,
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;
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 */
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);
}
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);
}
}
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);
}
"Cannot create instance: has no _type_");
return NULL;
}
- return GenericPyCData_new(type, args, kw);
+ return generic_pycdata_new(st, type, args, kw);
}
static PyObject *
}
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;
}
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;
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;
} \
} 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));
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
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;
}
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) {
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;
}
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)
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];
/**************************************************************/
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;
/*
* 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);
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;
*/
if (arg) {
int result;
- result = ConvParam(arg, index, pa);
+ result = ConvParam(st, arg, index, pa);
Py_DECREF(arg);
return result;
}
// 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;
*
* 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,
}
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;
}
* - 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;
Py_RETURN_NONE;
}
- ctypes_state *st = GLOBAL_STATE();
StgInfo *info;
if (PyStgInfo_FromType(st, restype, &info) < 0) {
return NULL;
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
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;
#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;
descr, source, helpfile, helpcontext,
progid);
if (obj) {
- ctypes_state *st = GLOBAL_STATE();
PyErr_SetObject((PyObject *)st->PyComError_Type, obj);
Py_DECREF(obj);
}
*
* - 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,
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;
}
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 ? */
}
}
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;
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)))
#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) {
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);
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;
return NULL;
}
- result = _ctypes_callproc((PPROC)func,
+ ctypes_state *st = GLOBAL_STATE();
+ result = _ctypes_callproc(st,
+ (PPROC)func,
arguments,
#ifdef MS_WIN32
NULL,
return NULL;
}
- result = _ctypes_callproc((PPROC)func,
+ ctypes_state *st = GLOBAL_STATE();
+ result = _ctypes_callproc(st,
+ (PPROC)func,
arguments,
#ifdef MS_WIN32
NULL,
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;
return NULL;
}
- parg = PyCArgObject_new();
+ parg = PyCArgObject_new(st);
if (parg == NULL)
return NULL;
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);
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;
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) {