diff -r ce070040e1a6 -r e0a551b4ec5c Lib/ctypes/test/test_pep3118.py --- a/Lib/ctypes/test/test_pep3118.py Sat May 10 13:24:58 2014 -0400 +++ b/Lib/ctypes/test/test_pep3118.py Sun May 11 00:04:50 2014 +0300 @@ -96,6 +96,9 @@ class aUnion(Union): _fields_ = [("a", c_int)] +class StructWithArrays(Structure): + _fields_ = [("x", c_long * 3 * 2), ("y", Point * 4)] + class Incomplete(Structure): pass @@ -145,10 +148,10 @@ ## arrays and pointers - (c_double * 4, "(4) 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 __metaclass__ will call the contructor StructUnionType_new. It replaces the tp_dict member with a new instance of StgDict, and initializes the C @@ -860,14 +902,21 @@ if (proto) { StgDictObject *itemdict = PyType_stgdict(proto); + const char *current_format; assert(itemdict); /* If itemdict->format is NULL, then this is a pointer to an incomplete type. We create a generic format string 'pointer to bytes' in this case. XXX Better would be to fix the format string later... */ - stgdict->format = _ctypes_alloc_format_string("&", - itemdict->format ? itemdict->format : "B"); + current_format = 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) { Py_DECREF((PyObject *)stgdict); return NULL; @@ -1245,7 +1294,6 @@ long length; int overflow; Py_ssize_t itemsize, itemalign; - char buf[32]; /* create the new instance (which is a class, since we are a metatype!) */ @@ -1295,13 +1343,7 @@ } assert(itemdict->format); - if (itemdict->format[0] == '(') { - 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); - } + stgdict->format = _ctypes_alloc_format_string(NULL, itemdict->format); if (stgdict->format == NULL) goto error; stgdict->ndim = itemdict->ndim + 1; diff -r ce070040e1a6 -r e0a551b4ec5c Modules/_ctypes/ctypes.h --- a/Modules/_ctypes/ctypes.h Sat May 10 13:24:58 2014 -0400 +++ b/Modules/_ctypes/ctypes.h Sun May 11 00:04:50 2014 +0300 @@ -357,6 +357,9 @@ 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_with_shape(int ndim, + const Py_ssize_t *shape, + const char *prefix, const char *suffix); extern int _ctypes_simple_instance(PyObject *obj); diff -r ce070040e1a6 -r e0a551b4ec5c Modules/_ctypes/stgdict.c --- a/Modules/_ctypes/stgdict.c Sat May 10 13:24:58 2014 -0400 +++ b/Modules/_ctypes/stgdict.c Sun May 11 00:04:50 2014 +0300 @@ -505,7 +505,12 @@ sprintf(buf, "%s:%s:", fieldfmt, fieldname); 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(buf);