aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--Modules/_ctypes/_ctypes.c14
-rw-r--r--Modules/_ctypes/callproc.c126
-rw-r--r--Modules/_ctypes/clinic/callproc.c.h143
3 files changed, 211 insertions, 72 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 55e5eee0eb0..8e4794866e8 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -2843,16 +2843,24 @@ PyCData_GetContainer(CDataObject *self)
while (self->b_base) {
self = self->b_base;
}
+ CDataObject *res = self;
+ Py_BEGIN_CRITICAL_SECTION(self);
+ // avoid using return directly in this block because critical section
+ // needs to be released before returning
if (self->b_objects == NULL) {
if (self->b_length) {
self->b_objects = PyDict_New();
- if (self->b_objects == NULL)
- return NULL;
+ if (self->b_objects == NULL) {
+ res = NULL;
+ goto exit;
+ }
} else {
self->b_objects = Py_NewRef(Py_None);
}
}
- return self;
+exit:;
+ Py_END_CRITICAL_SECTION();
+ return res;
}
static PyObject *
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index 158422fb9b0..352487ed964 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -106,8 +106,9 @@ module _ctypes
#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
#include "../_complex.h" // complex
#endif
-
+#define clinic_state() (get_module_state(module))
#include "clinic/callproc.c.h"
+#undef clinic_state
#define CTYPES_CAPSULE_NAME_PYMEM "_ctypes pymem"
@@ -1731,15 +1732,20 @@ call_cdeclfunction(PyObject *self, PyObject *args)
/*****************************************************************
* functions
*/
-PyDoc_STRVAR(sizeof_doc,
-"sizeof(C type) -> integer\n"
-"sizeof(C instance) -> integer\n"
-"Return the size in bytes of a C instance");
+
+/*[clinic input]
+_ctypes.sizeof
+ obj: object
+ /
+Return the size in bytes of a C instance.
+
+[clinic start generated code]*/
static PyObject *
-sizeof_func(PyObject *self, PyObject *obj)
+_ctypes_sizeof(PyObject *module, PyObject *obj)
+/*[clinic end generated code: output=ed38a3f364d7bd3e input=321fd0f65cb2d623]*/
{
- ctypes_state *st = get_module_state(self);
+ ctypes_state *st = get_module_state(module);
StgInfo *info;
if (PyStgInfo_FromType(st, obj, &info) < 0) {
@@ -1750,7 +1756,11 @@ sizeof_func(PyObject *self, PyObject *obj)
}
if (CDataObject_Check(st, obj)) {
- return PyLong_FromSsize_t(((CDataObject *)obj)->b_size);
+ PyObject *ret = NULL;
+ Py_BEGIN_CRITICAL_SECTION(obj);
+ ret = PyLong_FromSsize_t(((CDataObject *)obj)->b_size);
+ Py_END_CRITICAL_SECTION();
+ return ret;
}
PyErr_SetString(PyExc_TypeError,
"this type has no size");
@@ -1778,40 +1788,24 @@ align_func(PyObject *self, PyObject *obj)
return NULL;
}
-PyDoc_STRVAR(byref_doc,
-"byref(C instance[, offset=0]) -> byref-object\n"
-"Return a pointer lookalike to a C instance, only usable\n"
-"as function argument");
-/*
- * We must return something which can be converted to a parameter,
- * but still has a reference to self.
- */
+/*[clinic input]
+@critical_section obj
+_ctypes.byref
+ obj: object(subclass_of="clinic_state()->PyCData_Type")
+ offset: Py_ssize_t = 0
+ /
+Return a pointer lookalike to a C instance, only usable as function argument.
+
+[clinic start generated code]*/
+
static PyObject *
-byref(PyObject *self, PyObject *args)
+_ctypes_byref_impl(PyObject *module, PyObject *obj, Py_ssize_t offset)
+/*[clinic end generated code: output=60dec5ed520c71de input=6ec02d95d15fbd56]*/
{
- PyCArgObject *parg;
- PyObject *obj;
- PyObject *pyoffset = NULL;
- Py_ssize_t offset = 0;
-
- if (!PyArg_UnpackTuple(args, "byref", 1, 2,
- &obj, &pyoffset))
- return NULL;
- if (pyoffset) {
- offset = PyNumber_AsSsize_t(pyoffset, NULL);
- if (offset == -1 && PyErr_Occurred())
- return NULL;
- }
- 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'",
- Py_TYPE(obj)->tp_name);
- return NULL;
- }
+ ctypes_state *st = get_module_state(module);
- parg = PyCArgObject_new(st);
+ PyCArgObject *parg = PyCArgObject_new(st);
if (parg == NULL)
return NULL;
@@ -1822,19 +1816,19 @@ byref(PyObject *self, PyObject *args)
return (PyObject *)parg;
}
-PyDoc_STRVAR(addressof_doc,
-"addressof(C instance) -> integer\n"
-"Return the address of the C instance internal buffer");
+/*[clinic input]
+@critical_section obj
+_ctypes.addressof
+ obj: object(subclass_of="clinic_state()->PyCData_Type")
+ /
+Return the address of the C instance internal buffer
+
+[clinic start generated code]*/
static PyObject *
-addressof(PyObject *self, PyObject *obj)
+_ctypes_addressof_impl(PyObject *module, PyObject *obj)
+/*[clinic end generated code: output=30d8e80c4bab70c7 input=d83937d105d3a442]*/
{
- ctypes_state *st = get_module_state(self);
- if (!CDataObject_Check(st, obj)) {
- PyErr_SetString(PyExc_TypeError,
- "invalid type");
- return NULL;
- }
if (PySys_Audit("ctypes.addressof", "(O)", obj) < 0) {
return NULL;
}
@@ -1878,18 +1872,20 @@ My_Py_DECREF(PyObject *self, PyObject *arg)
return arg;
}
-static PyObject *
-resize(PyObject *self, PyObject *args)
-{
- CDataObject *obj;
- Py_ssize_t size;
+/*[clinic input]
+@critical_section obj
+_ctypes.resize
+ obj: object(subclass_of="clinic_state()->PyCData_Type", type="CDataObject *")
+ size: Py_ssize_t
+ /
- if (!PyArg_ParseTuple(args,
- "On:resize",
- &obj, &size))
- return NULL;
+[clinic start generated code]*/
- ctypes_state *st = get_module_state(self);
+static PyObject *
+_ctypes_resize_impl(PyObject *module, CDataObject *obj, Py_ssize_t size)
+/*[clinic end generated code: output=11c89c7dbdbcd53f input=bf5a6aaea8514261]*/
+{
+ ctypes_state *st = get_module_state(module);
StgInfo *info;
int result = PyStgInfo_FromObject(st, (PyObject *)obj, &info);
if (result < 0) {
@@ -2103,7 +2099,7 @@ PyMethodDef _ctypes_module_methods[] = {
CREATE_POINTER_INST_METHODDEF
{"_unpickle", unpickle, METH_VARARGS },
{"buffer_info", buffer_info, METH_O, "Return buffer interface information"},
- {"resize", resize, METH_VARARGS, "Resize the memory buffer of a ctypes instance"},
+ _CTYPES_RESIZE_METHODDEF
#ifdef MS_WIN32
{"get_last_error", get_last_error, METH_NOARGS},
{"set_last_error", set_last_error, METH_VARARGS},
@@ -2122,9 +2118,9 @@ PyMethodDef _ctypes_module_methods[] = {
{"_dyld_shared_cache_contains_path", py_dyld_shared_cache_contains_path, METH_VARARGS, "check if path is in the shared cache"},
#endif
{"alignment", align_func, METH_O, alignment_doc},
- {"sizeof", sizeof_func, METH_O, sizeof_doc},
- {"byref", byref, METH_VARARGS, byref_doc},
- {"addressof", addressof, METH_O, addressof_doc},
+ _CTYPES_SIZEOF_METHODDEF
+ _CTYPES_BYREF_METHODDEF
+ _CTYPES_ADDRESSOF_METHODDEF
{"call_function", call_function, METH_VARARGS },
{"call_cdeclfunction", call_cdeclfunction, METH_VARARGS },
{"PyObj_FromPtr", My_PyObj_FromPtr, METH_VARARGS },
@@ -2132,9 +2128,3 @@ PyMethodDef _ctypes_module_methods[] = {
{"Py_DECREF", My_Py_DECREF, METH_O },
{NULL, NULL} /* Sentinel */
};
-
-/*
- Local Variables:
- compile-command: "cd .. && python setup.py -q build -g && python setup.py -q build install --home ~"
- End:
-*/
diff --git a/Modules/_ctypes/clinic/callproc.c.h b/Modules/_ctypes/clinic/callproc.c.h
index a787693ae67..8a5c8f6427b 100644
--- a/Modules/_ctypes/clinic/callproc.c.h
+++ b/Modules/_ctypes/clinic/callproc.c.h
@@ -2,6 +2,147 @@
preserve
[clinic start generated code]*/
+#include "pycore_abstract.h" // _PyNumber_Index()
+#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
+#include "pycore_modsupport.h" // _PyArg_CheckPositional()
+
+PyDoc_STRVAR(_ctypes_sizeof__doc__,
+"sizeof($module, obj, /)\n"
+"--\n"
+"\n"
+"Return the size in bytes of a C instance.");
+
+#define _CTYPES_SIZEOF_METHODDEF \
+ {"sizeof", (PyCFunction)_ctypes_sizeof, METH_O, _ctypes_sizeof__doc__},
+
+PyDoc_STRVAR(_ctypes_byref__doc__,
+"byref($module, obj, offset=0, /)\n"
+"--\n"
+"\n"
+"Return a pointer lookalike to a C instance, only usable as function argument.");
+
+#define _CTYPES_BYREF_METHODDEF \
+ {"byref", _PyCFunction_CAST(_ctypes_byref), METH_FASTCALL, _ctypes_byref__doc__},
+
+static PyObject *
+_ctypes_byref_impl(PyObject *module, PyObject *obj, Py_ssize_t offset);
+
+static PyObject *
+_ctypes_byref(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *obj;
+ Py_ssize_t offset = 0;
+
+ if (!_PyArg_CheckPositional("byref", nargs, 1, 2)) {
+ goto exit;
+ }
+ if (!PyObject_TypeCheck(args[0], clinic_state()->PyCData_Type)) {
+ _PyArg_BadArgument("byref", "argument 1", (clinic_state()->PyCData_Type)->tp_name, args[0]);
+ goto exit;
+ }
+ obj = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ {
+ 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:
+ Py_BEGIN_CRITICAL_SECTION(obj);
+ return_value = _ctypes_byref_impl(module, obj, offset);
+ Py_END_CRITICAL_SECTION();
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_ctypes_addressof__doc__,
+"addressof($module, obj, /)\n"
+"--\n"
+"\n"
+"Return the address of the C instance internal buffer");
+
+#define _CTYPES_ADDRESSOF_METHODDEF \
+ {"addressof", (PyCFunction)_ctypes_addressof, METH_O, _ctypes_addressof__doc__},
+
+static PyObject *
+_ctypes_addressof_impl(PyObject *module, PyObject *obj);
+
+static PyObject *
+_ctypes_addressof(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ PyObject *obj;
+
+ if (!PyObject_TypeCheck(arg, clinic_state()->PyCData_Type)) {
+ _PyArg_BadArgument("addressof", "argument", (clinic_state()->PyCData_Type)->tp_name, arg);
+ goto exit;
+ }
+ obj = arg;
+ Py_BEGIN_CRITICAL_SECTION(obj);
+ return_value = _ctypes_addressof_impl(module, obj);
+ Py_END_CRITICAL_SECTION();
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_ctypes_resize__doc__,
+"resize($module, obj, size, /)\n"
+"--\n"
+"\n");
+
+#define _CTYPES_RESIZE_METHODDEF \
+ {"resize", _PyCFunction_CAST(_ctypes_resize), METH_FASTCALL, _ctypes_resize__doc__},
+
+static PyObject *
+_ctypes_resize_impl(PyObject *module, CDataObject *obj, Py_ssize_t size);
+
+static PyObject *
+_ctypes_resize(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ CDataObject *obj;
+ Py_ssize_t size;
+
+ if (!_PyArg_CheckPositional("resize", nargs, 2, 2)) {
+ goto exit;
+ }
+ if (!PyObject_TypeCheck(args[0], clinic_state()->PyCData_Type)) {
+ _PyArg_BadArgument("resize", "argument 1", (clinic_state()->PyCData_Type)->tp_name, args[0]);
+ goto exit;
+ }
+ obj = (CDataObject *)args[0];
+ {
+ 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;
+ }
+ size = ival;
+ }
+ Py_BEGIN_CRITICAL_SECTION(obj);
+ return_value = _ctypes_resize_impl(module, obj, size);
+ Py_END_CRITICAL_SECTION();
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(create_pointer_type__doc__,
"POINTER($module, type, /)\n"
"--\n"
@@ -29,4 +170,4 @@ PyDoc_STRVAR(create_pointer_inst__doc__,
#define CREATE_POINTER_INST_METHODDEF \
{"pointer", (PyCFunction)create_pointer_inst, METH_O, create_pointer_inst__doc__},
-/*[clinic end generated code: output=51b311ea369e5adf input=a9049054013a1b77]*/
+/*[clinic end generated code: output=46a3841cbe5ddc96 input=a9049054013a1b77]*/