mirror of
https://github.com/python/cpython.git
synced 2025-09-14 20:56:06 +00:00
support pep 3118 format strings for ctypes objects with nontrivial shapes (closes #10744)
Patch by Matti Picus.
This commit is contained in:
parent
5d52022406
commit
5eb6b39210
5 changed files with 74 additions and 15 deletions
|
@ -96,6 +96,9 @@ class EmptyStruct(Structure):
|
||||||
class aUnion(Union):
|
class aUnion(Union):
|
||||||
_fields_ = [("a", c_int)]
|
_fields_ = [("a", c_int)]
|
||||||
|
|
||||||
|
class StructWithArrays(Structure):
|
||||||
|
_fields_ = [("x", c_long * 3 * 2), ("y", Point * 4)]
|
||||||
|
|
||||||
class Incomplete(Structure):
|
class Incomplete(Structure):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -145,10 +148,10 @@ native_types = [
|
||||||
|
|
||||||
## arrays and pointers
|
## arrays and pointers
|
||||||
|
|
||||||
(c_double * 4, "(4)<d", (4,), c_double),
|
(c_double * 4, "<d", (4,), c_double),
|
||||||
(c_float * 4 * 3 * 2, "(2,3,4)<f", (2,3,4), c_float),
|
(c_float * 4 * 3 * 2, "<f", (2,3,4), c_float),
|
||||||
(POINTER(c_short) * 2, "(2)&<h", (2,), POINTER(c_short)),
|
(POINTER(c_short) * 2, "&<h", (2,), POINTER(c_short)),
|
||||||
(POINTER(c_short) * 2 * 3, "(3,2)&<h", (3,2,), POINTER(c_short)),
|
(POINTER(c_short) * 2 * 3, "&<h", (3,2,), POINTER(c_short)),
|
||||||
(POINTER(c_short * 2), "&(2)<h", (), POINTER(c_short)),
|
(POINTER(c_short * 2), "&(2)<h", (), POINTER(c_short)),
|
||||||
|
|
||||||
## structures and unions
|
## structures and unions
|
||||||
|
@ -160,6 +163,9 @@ native_types = [
|
||||||
(EmptyStruct, "T{}", (), EmptyStruct),
|
(EmptyStruct, "T{}", (), EmptyStruct),
|
||||||
# the pep does't support unions
|
# the pep does't support unions
|
||||||
(aUnion, "B", (), aUnion),
|
(aUnion, "B", (), aUnion),
|
||||||
|
# structure with sub-arrays
|
||||||
|
(StructWithArrays, "T{(2,3)<l:x:(4)T{<l:x:<l:y:}:y:}", (), StructWithArrays),
|
||||||
|
(StructWithArrays * 3, "T{(2,3)<l:x:(4)T{<l:x:<l:y:}:y:}", (3,), StructWithArrays),
|
||||||
|
|
||||||
## pointer to incomplete structure
|
## pointer to incomplete structure
|
||||||
(Incomplete, "B", (), Incomplete),
|
(Incomplete, "B", (), Incomplete),
|
||||||
|
|
|
@ -23,6 +23,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #10744: Fix PEP 3118 format strings on ctypes objects with a nontrivial
|
||||||
|
shape.
|
||||||
|
|
||||||
- Issue #20998: Fixed re.fullmatch() of repeated single character pattern
|
- Issue #20998: Fixed re.fullmatch() of repeated single character pattern
|
||||||
with ignore case. Original patch by Matthew Barnett.
|
with ignore case. Original patch by Matthew Barnett.
|
||||||
|
|
||||||
|
|
|
@ -288,6 +288,48 @@ _ctypes_alloc_format_string(const char *prefix, const char *suffix)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Allocate a memory block for a pep3118 format string, adding
|
||||||
|
the given prefix (if non-null), an additional shape prefix, and a suffix.
|
||||||
|
Returns NULL on failure, with the error indicator set. If called with
|
||||||
|
a suffix of NULL the error indicator must already be set.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
_ctypes_alloc_format_string_with_shape(int ndim, const Py_ssize_t *shape,
|
||||||
|
const char *prefix, const char *suffix)
|
||||||
|
{
|
||||||
|
char *new_prefix;
|
||||||
|
char *result;
|
||||||
|
char buf[32];
|
||||||
|
int prefix_len;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
prefix_len = 32 * ndim + 3;
|
||||||
|
if (prefix)
|
||||||
|
prefix_len += strlen(prefix);
|
||||||
|
new_prefix = PyMem_Malloc(prefix_len);
|
||||||
|
if (new_prefix == NULL)
|
||||||
|
return NULL;
|
||||||
|
new_prefix[0] = '\0';
|
||||||
|
if (prefix)
|
||||||
|
strcpy(new_prefix, prefix);
|
||||||
|
if (ndim > 0) {
|
||||||
|
/* Add the prefix "(shape[0],shape[1],...,shape[ndim-1])" */
|
||||||
|
strcat(new_prefix, "(");
|
||||||
|
for (k = 0; k < ndim; ++k) {
|
||||||
|
if (k < ndim-1) {
|
||||||
|
sprintf(buf, "%"PY_FORMAT_SIZE_T"d,", shape[k]);
|
||||||
|
} else {
|
||||||
|
sprintf(buf, "%"PY_FORMAT_SIZE_T"d)", shape[k]);
|
||||||
|
}
|
||||||
|
strcat(new_prefix, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = _ctypes_alloc_format_string(new_prefix, suffix);
|
||||||
|
PyMem_Free(new_prefix);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PyCStructType_Type - a meta type/class. Creating a new class using this one as
|
PyCStructType_Type - a meta type/class. Creating a new class using this one as
|
||||||
__metaclass__ will call the contructor StructUnionType_new. It replaces the
|
__metaclass__ will call the contructor StructUnionType_new. It replaces the
|
||||||
|
@ -860,14 +902,21 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
|
|
||||||
if (proto) {
|
if (proto) {
|
||||||
StgDictObject *itemdict = PyType_stgdict(proto);
|
StgDictObject *itemdict = PyType_stgdict(proto);
|
||||||
|
const char *current_format;
|
||||||
assert(itemdict);
|
assert(itemdict);
|
||||||
/* If itemdict->format is NULL, then this is a pointer to an
|
/* If itemdict->format is NULL, then this is a pointer to an
|
||||||
incomplete type. We create a generic format string
|
incomplete type. We create a generic format string
|
||||||
'pointer to bytes' in this case. XXX Better would be to
|
'pointer to bytes' in this case. XXX Better would be to
|
||||||
fix the format string later...
|
fix the format string later...
|
||||||
*/
|
*/
|
||||||
stgdict->format = _ctypes_alloc_format_string("&",
|
current_format = itemdict->format ? itemdict->format : "B";
|
||||||
itemdict->format ? itemdict->format : "B");
|
if (itemdict->shape != NULL) {
|
||||||
|
/* pointer to an array: the shape needs to be prefixed */
|
||||||
|
stgdict->format = _ctypes_alloc_format_string_with_shape(
|
||||||
|
itemdict->ndim, itemdict->shape, "&", current_format);
|
||||||
|
} else {
|
||||||
|
stgdict->format = _ctypes_alloc_format_string("&", current_format);
|
||||||
|
}
|
||||||
if (stgdict->format == NULL) {
|
if (stgdict->format == NULL) {
|
||||||
Py_DECREF((PyObject *)stgdict);
|
Py_DECREF((PyObject *)stgdict);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1245,7 +1294,6 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
long length;
|
long length;
|
||||||
int overflow;
|
int overflow;
|
||||||
Py_ssize_t itemsize, itemalign;
|
Py_ssize_t itemsize, itemalign;
|
||||||
char buf[32];
|
|
||||||
|
|
||||||
/* create the new instance (which is a class,
|
/* create the new instance (which is a class,
|
||||||
since we are a metatype!) */
|
since we are a metatype!) */
|
||||||
|
@ -1295,13 +1343,7 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(itemdict->format);
|
assert(itemdict->format);
|
||||||
if (itemdict->format[0] == '(') {
|
stgdict->format = _ctypes_alloc_format_string(NULL, itemdict->format);
|
||||||
sprintf(buf, "(%ld,", length);
|
|
||||||
stgdict->format = _ctypes_alloc_format_string(buf, itemdict->format+1);
|
|
||||||
} else {
|
|
||||||
sprintf(buf, "(%ld)", length);
|
|
||||||
stgdict->format = _ctypes_alloc_format_string(buf, itemdict->format);
|
|
||||||
}
|
|
||||||
if (stgdict->format == NULL)
|
if (stgdict->format == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
stgdict->ndim = itemdict->ndim + 1;
|
stgdict->ndim = itemdict->ndim + 1;
|
||||||
|
|
|
@ -357,6 +357,9 @@ extern void _ctypes_add_traceback(char *, char *, int);
|
||||||
|
|
||||||
extern PyObject *PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr);
|
extern PyObject *PyCData_FromBaseObj(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,
|
||||||
|
const Py_ssize_t *shape,
|
||||||
|
const char *prefix, const char *suffix);
|
||||||
|
|
||||||
extern int _ctypes_simple_instance(PyObject *obj);
|
extern int _ctypes_simple_instance(PyObject *obj);
|
||||||
|
|
||||||
|
|
|
@ -505,7 +505,12 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct
|
||||||
sprintf(buf, "%s:%s:", fieldfmt, fieldname);
|
sprintf(buf, "%s:%s:", fieldfmt, fieldname);
|
||||||
|
|
||||||
ptr = stgdict->format;
|
ptr = stgdict->format;
|
||||||
stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf);
|
if (dict->shape != NULL) {
|
||||||
|
stgdict->format = _ctypes_alloc_format_string_with_shape(
|
||||||
|
dict->ndim, dict->shape, stgdict->format, buf);
|
||||||
|
} else {
|
||||||
|
stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf);
|
||||||
|
}
|
||||||
PyMem_Free(ptr);
|
PyMem_Free(ptr);
|
||||||
PyMem_Free(buf);
|
PyMem_Free(buf);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue