gh-117142: Port _ctypes to multi-phase init (GH-117181)

This commit is contained in:
neonene 2024-04-10 20:00:01 +09:00 committed by GitHub
parent 4bb7d121bc
commit ef4118222b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 1125 additions and 178 deletions

View file

@ -4,6 +4,7 @@
import unittest
from test import support
from test.support import import_helper
from test.support import script_helper
_ctypes_test = import_helper.import_module("_ctypes_test")
@ -110,5 +111,18 @@ def func():
func()
class ModuleIsolationTest(unittest.TestCase):
def test_finalize(self):
# check if gc_decref() succeeds
script = (
"import ctypes;"
"import sys;"
"del sys.modules['_ctypes'];"
"import _ctypes;"
"exit()"
)
script_helper.assert_python_ok("-c", script)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1 @@
Convert :mod:`!_ctypes` to multi-phase initialisation (:pep:`489`).

File diff suppressed because it is too large Load diff

View file

@ -136,6 +136,8 @@ TryAddRef(PyObject *cnv, CDataObject *obj)
* Call the python object with all arguments
*
*/
// BEWARE: The GIL needs to be held throughout the function
static void _CallPythonObject(ctypes_state *st,
void *mem,
ffi_type *restype,
@ -149,7 +151,6 @@ static void _CallPythonObject(ctypes_state *st,
Py_ssize_t i = 0, j = 0, nargs = 0;
PyObject *error_object = NULL;
int *space;
PyGILState_STATE state = PyGILState_Ensure();
assert(PyTuple_Check(converters));
nargs = PyTuple_GET_SIZE(converters);
@ -294,7 +295,6 @@ static void _CallPythonObject(ctypes_state *st,
for (j = 0; j < i; j++) {
Py_DECREF(args[j]);
}
PyGILState_Release(state);
}
static void closure_fcn(ffi_cif *cif,
@ -302,8 +302,10 @@ static void closure_fcn(ffi_cif *cif,
void **args,
void *userdata)
{
PyGILState_STATE state = PyGILState_Ensure();
CThunkObject *p = (CThunkObject *)userdata;
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state_by_class(Py_TYPE(p));
_CallPythonObject(st,
resp,
@ -313,6 +315,8 @@ static void closure_fcn(ffi_cif *cif,
p->converters,
p->flags,
args);
PyGILState_Release(state);
}
static CThunkObject* CThunkObject_new(ctypes_state *st, Py_ssize_t nargs)

View file

@ -201,7 +201,7 @@ static PyObject *
get_error_internal(PyObject *self, PyObject *args, int index)
{
int *space;
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state(self);
PyObject *errobj = _ctypes_get_errobj(st, &space);
PyObject *result;
@ -222,7 +222,7 @@ set_error_internal(PyObject *self, PyObject *args, int index)
if (!PyArg_ParseTuple(args, "i", &new_errno)) {
return NULL;
}
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state(self);
errobj = _ctypes_get_errobj(st, &space);
if (errobj == NULL)
return NULL;
@ -1464,7 +1464,7 @@ copy_com_pointer(PyObject *self, PyObject *args)
return NULL;
a.keep = b.keep = NULL;
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state(self);
if (ConvParam(st, p1, 0, &a) < 0 || ConvParam(st, p2, 1, &b) < 0) {
goto done;
}
@ -1646,7 +1646,7 @@ call_function(PyObject *self, PyObject *args)
return NULL;
}
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state(self);
result = _ctypes_callproc(st,
(PPROC)func,
arguments,
@ -1683,7 +1683,7 @@ call_cdeclfunction(PyObject *self, PyObject *args)
return NULL;
}
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state(self);
result = _ctypes_callproc(st,
(PPROC)func,
arguments,
@ -1709,7 +1709,7 @@ PyDoc_STRVAR(sizeof_doc,
static PyObject *
sizeof_func(PyObject *self, PyObject *obj)
{
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state(self);
StgInfo *info;
if (PyStgInfo_FromType(st, obj, &info) < 0) {
@ -1735,7 +1735,7 @@ PyDoc_STRVAR(alignment_doc,
static PyObject *
align_func(PyObject *self, PyObject *obj)
{
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state(self);
StgInfo *info;
if (PyStgInfo_FromAny(st, obj, &info) < 0) {
return NULL;
@ -1773,7 +1773,7 @@ byref(PyObject *self, PyObject *args)
if (offset == -1 && PyErr_Occurred())
return NULL;
}
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state(self);
if (!CDataObject_Check(st, obj)) {
PyErr_Format(PyExc_TypeError,
"byref() argument must be a ctypes instance, not '%s'",
@ -1799,7 +1799,7 @@ PyDoc_STRVAR(addressof_doc,
static PyObject *
addressof(PyObject *self, PyObject *obj)
{
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state(self);
if (!CDataObject_Check(st, obj)) {
PyErr_SetString(PyExc_TypeError,
"invalid type");
@ -1858,7 +1858,7 @@ resize(PyObject *self, PyObject *args)
&obj, &size))
return NULL;
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state(self);
StgInfo *info;
int result = PyStgInfo_FromObject(st, (PyObject *)obj, &info);
if (result < 0) {
@ -1956,7 +1956,8 @@ create_pointer_type(PyObject *module, PyObject *cls)
PyTypeObject *typ;
PyObject *key;
ctypes_state *st = GLOBAL_STATE();
assert(module);
ctypes_state *st = get_module_state(module);
if (PyDict_GetItemRef(st->_ctypes_ptrtype_cache, cls, &result) != 0) {
// found or error
return result;
@ -2019,12 +2020,12 @@ create_pointer_inst(PyObject *module, PyObject *arg)
PyObject *result;
PyObject *typ;
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state(module);
if (PyDict_GetItemRef(st->_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg), &typ) < 0) {
return NULL;
}
if (typ == NULL) {
typ = create_pointer_type(NULL, (PyObject *)Py_TYPE(arg));
typ = create_pointer_type(module, (PyObject *)Py_TYPE(arg));
if (typ == NULL)
return NULL;
}
@ -2039,7 +2040,7 @@ buffer_info(PyObject *self, PyObject *arg)
PyObject *shape;
Py_ssize_t i;
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state(self);
StgInfo *info;
if (PyStgInfo_FromAny(st, arg, &info) < 0) {
return NULL;

View file

@ -216,7 +216,7 @@ PyCField_set(CFieldObject *self, PyObject *inst, PyObject *value)
{
CDataObject *dst;
char *ptr;
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state_by_class(Py_TYPE(self));
if (!CDataObject_Check(st, inst)) {
PyErr_SetString(PyExc_TypeError,
"not a ctype instance");
@ -240,7 +240,7 @@ PyCField_get(CFieldObject *self, PyObject *inst, PyTypeObject *type)
if (inst == NULL) {
return Py_NewRef(self);
}
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state_by_class(Py_TYPE(self));
if (!CDataObject_Check(st, inst)) {
PyErr_SetString(PyExc_TypeError,
"not a ctype instance");

610
Modules/_ctypes/clinic/_ctypes.c.h generated Normal file
View file

@ -0,0 +1,610 @@
/*[clinic input]
preserve
[clinic start generated code]*/
#include "pycore_abstract.h" // _PyNumber_Index()
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
PyDoc_STRVAR(_ctypes_CType_Type___sizeof____doc__,
"__sizeof__($self, /)\n"
"--\n"
"\n"
"Return memory consumption of the type object.");
#define _CTYPES_CTYPE_TYPE___SIZEOF___METHODDEF \
{"__sizeof__", _PyCFunction_CAST(_ctypes_CType_Type___sizeof__), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _ctypes_CType_Type___sizeof____doc__},
static PyObject *
_ctypes_CType_Type___sizeof___impl(PyObject *self, PyTypeObject *cls);
static PyObject *
_ctypes_CType_Type___sizeof__(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
PyErr_SetString(PyExc_TypeError, "__sizeof__() takes no arguments");
return NULL;
}
return _ctypes_CType_Type___sizeof___impl(self, cls);
}
PyDoc_STRVAR(CDataType_from_address__doc__,
"from_address($self, value, /)\n"
"--\n"
"\n"
"C.from_address(integer) -> C instance\n"
"\n"
"Access a C instance at the specified address.");
#define CDATATYPE_FROM_ADDRESS_METHODDEF \
{"from_address", _PyCFunction_CAST(CDataType_from_address), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, CDataType_from_address__doc__},
static PyObject *
CDataType_from_address_impl(PyObject *type, PyTypeObject *cls,
PyObject *value);
static PyObject *
CDataType_from_address(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
#else
# define KWTUPLE NULL
#endif
static const char * const _keywords[] = {"", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "from_address",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *value;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
value = args[0];
return_value = CDataType_from_address_impl(type, cls, value);
exit:
return return_value;
}
PyDoc_STRVAR(CDataType_from_buffer__doc__,
"from_buffer($self, obj, offset=0, /)\n"
"--\n"
"\n"
"C.from_buffer(object, offset=0) -> C instance\n"
"\n"
"Create a C instance from a writeable buffer.");
#define CDATATYPE_FROM_BUFFER_METHODDEF \
{"from_buffer", _PyCFunction_CAST(CDataType_from_buffer), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, CDataType_from_buffer__doc__},
static PyObject *
CDataType_from_buffer_impl(PyObject *type, PyTypeObject *cls, PyObject *obj,
Py_ssize_t offset);
static PyObject *
CDataType_from_buffer(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
#else
# define KWTUPLE NULL
#endif
static const char * const _keywords[] = {"", "", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "from_buffer",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[2];
PyObject *obj;
Py_ssize_t offset = 0;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
if (!args) {
goto exit;
}
obj = args[0];
if (nargs < 2) {
goto skip_optional_posonly;
}
{
Py_ssize_t ival = -1;
PyObject *iobj = _PyNumber_Index(args[1]);
if (iobj != NULL) {
ival = PyLong_AsSsize_t(iobj);
Py_DECREF(iobj);
}
if (ival == -1 && PyErr_Occurred()) {
goto exit;
}
offset = ival;
}
skip_optional_posonly:
return_value = CDataType_from_buffer_impl(type, cls, obj, offset);
exit:
return return_value;
}
PyDoc_STRVAR(CDataType_from_buffer_copy__doc__,
"from_buffer_copy($self, buffer, offset=0, /)\n"
"--\n"
"\n"
"C.from_buffer_copy(object, offset=0) -> C instance\n"
"\n"
"Create a C instance from a readable buffer.");
#define CDATATYPE_FROM_BUFFER_COPY_METHODDEF \
{"from_buffer_copy", _PyCFunction_CAST(CDataType_from_buffer_copy), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, CDataType_from_buffer_copy__doc__},
static PyObject *
CDataType_from_buffer_copy_impl(PyObject *type, PyTypeObject *cls,
Py_buffer *buffer, Py_ssize_t offset);
static PyObject *
CDataType_from_buffer_copy(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
#else
# define KWTUPLE NULL
#endif
static const char * const _keywords[] = {"", "", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "from_buffer_copy",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[2];
Py_buffer buffer = {NULL, NULL};
Py_ssize_t offset = 0;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
if (!args) {
goto exit;
}
if (PyObject_GetBuffer(args[0], &buffer, PyBUF_SIMPLE) != 0) {
goto exit;
}
if (nargs < 2) {
goto skip_optional_posonly;
}
{
Py_ssize_t ival = -1;
PyObject *iobj = _PyNumber_Index(args[1]);
if (iobj != NULL) {
ival = PyLong_AsSsize_t(iobj);
Py_DECREF(iobj);
}
if (ival == -1 && PyErr_Occurred()) {
goto exit;
}
offset = ival;
}
skip_optional_posonly:
return_value = CDataType_from_buffer_copy_impl(type, cls, &buffer, offset);
exit:
/* Cleanup for buffer */
if (buffer.obj) {
PyBuffer_Release(&buffer);
}
return return_value;
}
PyDoc_STRVAR(CDataType_in_dll__doc__,
"in_dll($self, dll, name, /)\n"
"--\n"
"\n"
"C.in_dll(dll, name) -> C instance\n"
"\n"
"Access a C instance in a dll.");
#define CDATATYPE_IN_DLL_METHODDEF \
{"in_dll", _PyCFunction_CAST(CDataType_in_dll), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, CDataType_in_dll__doc__},
static PyObject *
CDataType_in_dll_impl(PyObject *type, PyTypeObject *cls, PyObject *dll,
const char *name);
static PyObject *
CDataType_in_dll(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
#else
# define KWTUPLE NULL
#endif
static const char * const _keywords[] = {"", "", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "in_dll",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[2];
PyObject *dll;
const char *name;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
if (!args) {
goto exit;
}
dll = args[0];
if (!PyUnicode_Check(args[1])) {
_PyArg_BadArgument("in_dll", "argument 2", "str", args[1]);
goto exit;
}
Py_ssize_t name_length;
name = PyUnicode_AsUTF8AndSize(args[1], &name_length);
if (name == NULL) {
goto exit;
}
if (strlen(name) != (size_t)name_length) {
PyErr_SetString(PyExc_ValueError, "embedded null character");
goto exit;
}
return_value = CDataType_in_dll_impl(type, cls, dll, name);
exit:
return return_value;
}
PyDoc_STRVAR(CDataType_from_param__doc__,
"from_param($self, value, /)\n"
"--\n"
"\n"
"Convert a Python object into a function call parameter.");
#define CDATATYPE_FROM_PARAM_METHODDEF \
{"from_param", _PyCFunction_CAST(CDataType_from_param), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, CDataType_from_param__doc__},
static PyObject *
CDataType_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value);
static PyObject *
CDataType_from_param(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
#else
# define KWTUPLE NULL
#endif
static const char * const _keywords[] = {"", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "from_param",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *value;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
value = args[0];
return_value = CDataType_from_param_impl(type, cls, value);
exit:
return return_value;
}
PyDoc_STRVAR(PyCPointerType_set_type__doc__,
"set_type($self, type, /)\n"
"--\n"
"\n");
#define PYCPOINTERTYPE_SET_TYPE_METHODDEF \
{"set_type", _PyCFunction_CAST(PyCPointerType_set_type), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, PyCPointerType_set_type__doc__},
static PyObject *
PyCPointerType_set_type_impl(PyTypeObject *self, PyTypeObject *cls,
PyObject *type);
static PyObject *
PyCPointerType_set_type(PyTypeObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
#else
# define KWTUPLE NULL
#endif
static const char * const _keywords[] = {"", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "set_type",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *type;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
type = args[0];
return_value = PyCPointerType_set_type_impl(self, cls, type);
exit:
return return_value;
}
PyDoc_STRVAR(PyCPointerType_from_param__doc__,
"from_param($self, value, /)\n"
"--\n"
"\n"
"Convert a Python object into a function call parameter.");
#define PYCPOINTERTYPE_FROM_PARAM_METHODDEF \
{"from_param", _PyCFunction_CAST(PyCPointerType_from_param), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, PyCPointerType_from_param__doc__},
static PyObject *
PyCPointerType_from_param_impl(PyObject *type, PyTypeObject *cls,
PyObject *value);
static PyObject *
PyCPointerType_from_param(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
#else
# define KWTUPLE NULL
#endif
static const char * const _keywords[] = {"", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "from_param",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *value;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
value = args[0];
return_value = PyCPointerType_from_param_impl(type, cls, value);
exit:
return return_value;
}
PyDoc_STRVAR(c_wchar_p_from_param__doc__,
"from_param($self, value, /)\n"
"--\n"
"\n");
#define C_WCHAR_P_FROM_PARAM_METHODDEF \
{"from_param", _PyCFunction_CAST(c_wchar_p_from_param), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, c_wchar_p_from_param__doc__},
static PyObject *
c_wchar_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value);
static PyObject *
c_wchar_p_from_param(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
#else
# define KWTUPLE NULL
#endif
static const char * const _keywords[] = {"", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "from_param",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *value;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
value = args[0];
return_value = c_wchar_p_from_param_impl(type, cls, value);
exit:
return return_value;
}
PyDoc_STRVAR(c_char_p_from_param__doc__,
"from_param($self, value, /)\n"
"--\n"
"\n");
#define C_CHAR_P_FROM_PARAM_METHODDEF \
{"from_param", _PyCFunction_CAST(c_char_p_from_param), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, c_char_p_from_param__doc__},
static PyObject *
c_char_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value);
static PyObject *
c_char_p_from_param(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
#else
# define KWTUPLE NULL
#endif
static const char * const _keywords[] = {"", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "from_param",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *value;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
value = args[0];
return_value = c_char_p_from_param_impl(type, cls, value);
exit:
return return_value;
}
PyDoc_STRVAR(c_void_p_from_param__doc__,
"from_param($self, value, /)\n"
"--\n"
"\n");
#define C_VOID_P_FROM_PARAM_METHODDEF \
{"from_param", _PyCFunction_CAST(c_void_p_from_param), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, c_void_p_from_param__doc__},
static PyObject *
c_void_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value);
static PyObject *
c_void_p_from_param(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
#else
# define KWTUPLE NULL
#endif
static const char * const _keywords[] = {"", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "from_param",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *value;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
value = args[0];
return_value = c_void_p_from_param_impl(type, cls, value);
exit:
return return_value;
}
PyDoc_STRVAR(PyCSimpleType_from_param__doc__,
"from_param($self, value, /)\n"
"--\n"
"\n"
"Convert a Python object into a function call parameter.");
#define PYCSIMPLETYPE_FROM_PARAM_METHODDEF \
{"from_param", _PyCFunction_CAST(PyCSimpleType_from_param), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, PyCSimpleType_from_param__doc__},
static PyObject *
PyCSimpleType_from_param_impl(PyObject *type, PyTypeObject *cls,
PyObject *value);
static PyObject *
PyCSimpleType_from_param(PyObject *type, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
#else
# define KWTUPLE NULL
#endif
static const char * const _keywords[] = {"", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "from_param",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *value;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
value = args[0];
return_value = PyCSimpleType_from_param_impl(type, cls, value);
exit:
return return_value;
}
PyDoc_STRVAR(PyCData_reduce__doc__,
"__reduce__($self, /)\n"
"--\n"
"\n");
#define PYCDATA_REDUCE_METHODDEF \
{"__reduce__", _PyCFunction_CAST(PyCData_reduce), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, PyCData_reduce__doc__},
static PyObject *
PyCData_reduce_impl(PyObject *myself, PyTypeObject *cls);
static PyObject *
PyCData_reduce(PyObject *myself, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
PyErr_SetString(PyExc_TypeError, "__reduce__() takes no arguments");
return NULL;
}
return PyCData_reduce_impl(myself, cls);
}
PyDoc_STRVAR(Simple_from_outparm__doc__,
"__ctypes_from_outparam__($self, /)\n"
"--\n"
"\n");
#define SIMPLE_FROM_OUTPARM_METHODDEF \
{"__ctypes_from_outparam__", _PyCFunction_CAST(Simple_from_outparm), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, Simple_from_outparm__doc__},
static PyObject *
Simple_from_outparm_impl(PyObject *self, PyTypeObject *cls);
static PyObject *
Simple_from_outparm(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
PyErr_SetString(PyExc_TypeError, "__ctypes_from_outparam__() takes no arguments");
return NULL;
}
return Simple_from_outparm_impl(self, cls);
}
/*[clinic end generated code: output=9c6539a3559e6088 input=a9049054013a1b77]*/

View file

@ -2,6 +2,9 @@
# include <alloca.h>
#endif
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_typeobject.h" // _PyType_GetModuleState()
#ifndef MS_WIN32
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
@ -70,9 +73,48 @@ typedef struct {
PyObject *swapped_suffix;
} ctypes_state;
extern ctypes_state global_state;
#define GLOBAL_STATE() (&global_state)
extern struct PyModuleDef _ctypesmodule;
static inline ctypes_state *
get_module_state(PyObject *module)
{
void *state = _PyModule_GetState(module);
assert(state != NULL);
return (ctypes_state *)state;
}
static inline ctypes_state *
get_module_state_by_class(PyTypeObject *cls)
{
ctypes_state *state = (ctypes_state *)_PyType_GetModuleState(cls);
assert(state != NULL);
return state;
}
static inline ctypes_state *
get_module_state_by_def(PyTypeObject *cls)
{
PyObject *mod = PyType_GetModuleByDef(cls, &_ctypesmodule);
assert(mod != NULL);
return get_module_state(mod);
}
static inline ctypes_state *
get_module_state_by_def_final(PyTypeObject *cls)
{
if (cls->tp_mro == NULL) {
return NULL;
}
PyObject *mod = PyType_GetModuleByDef(cls, &_ctypesmodule);
if (mod == NULL) {
PyErr_Clear();
return NULL;
}
return get_module_state(mod);
}
extern PyType_Spec carg_spec;
extern PyType_Spec cfield_spec;

View file

@ -94,7 +94,7 @@ MakeFields(PyObject *type, CFieldObject *descr,
if (fieldlist == NULL)
return -1;
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state_by_class(Py_TYPE(descr));
PyTypeObject *cfield_tp = st->PyCField_Type;
for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) {
PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */
@ -175,7 +175,7 @@ MakeAnonFields(PyObject *type)
if (anon_names == NULL)
return -1;
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state_by_def(Py_TYPE(type));
PyTypeObject *cfield_tp = st->PyCField_Type;
for (i = 0; i < PySequence_Fast_GET_SIZE(anon_names); ++i) {
PyObject *fname = PySequence_Fast_GET_ITEM(anon_names, i); /* borrowed */
@ -318,7 +318,7 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct
return -1;
}
ctypes_state *st = GLOBAL_STATE();
ctypes_state *st = get_module_state_by_def(Py_TYPE(type));
StgInfo *stginfo;
if (PyStgInfo_FromType(st, type, &stginfo) < 0) {
return -1;

View file

@ -198,6 +198,7 @@ Python/pystate.c - _Py_tss_tstate -
Include/internal/pycore_blocks_output_buffer.h - BUFFER_BLOCK_SIZE -
Modules/_csv.c - quote_styles -
Modules/_ctypes/_ctypes.c - _ctypesmodule -
Modules/_ctypes/cfield.c - ffi_type_double -
Modules/_ctypes/cfield.c - ffi_type_float -
Modules/_ctypes/cfield.c - ffi_type_longdouble -

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