mirror of https://github.com/python/cpython
gh-76963: PEP3118 itemsize of an empty ctypes array should not be 0 (GH-5576)
The itemsize returned in a memoryview of a ctypes array is now computed from the item type, instead of dividing the total size by the length and assuming that the length is not zero.
This commit is contained in:
parent
73c08eeaff
commit
84bc6a4f25
|
@ -176,7 +176,9 @@ native_types = [
|
|||
## arrays and pointers
|
||||
|
||||
(c_double * 4, "<d", (4,), c_double),
|
||||
(c_double * 0, "<d", (0,), c_double),
|
||||
(c_float * 4 * 3 * 2, "<f", (2,3,4), c_float),
|
||||
(c_float * 4 * 0 * 2, "<f", (2,0,4), c_float),
|
||||
(POINTER(c_short) * 2, "&<" + s_short, (2,), POINTER(c_short)),
|
||||
(POINTER(c_short) * 2 * 3, "&<" + s_short, (3,2,), POINTER(c_short)),
|
||||
(POINTER(c_short * 2), "&(2)<" + s_short, (), POINTER(c_short)),
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
``ctypes`` arrays of length 0 now report a correct itemsize when a
|
||||
``memoryview`` is constructed from them, rather than always giving a value
|
||||
of 0.
|
|
@ -2731,11 +2731,33 @@ static PyMemberDef PyCData_members[] = {
|
|||
{ NULL },
|
||||
};
|
||||
|
||||
static int PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags)
|
||||
/* Find the innermost type of an array type, returning a borrowed reference */
|
||||
static PyObject *
|
||||
PyCData_item_type(PyObject *type)
|
||||
{
|
||||
if (PyCArrayTypeObject_Check(type)) {
|
||||
StgDictObject *stg_dict;
|
||||
PyObject *elem_type;
|
||||
|
||||
/* asserts used here as these are all guaranteed by construction */
|
||||
stg_dict = PyType_stgdict(type);
|
||||
assert(stg_dict);
|
||||
elem_type = stg_dict->proto;
|
||||
assert(elem_type);
|
||||
return PyCData_item_type(elem_type);
|
||||
}
|
||||
else {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags)
|
||||
{
|
||||
CDataObject *self = (CDataObject *)myself;
|
||||
StgDictObject *dict = PyObject_stgdict(myself);
|
||||
Py_ssize_t i;
|
||||
PyObject *item_type = PyCData_item_type((PyObject*)Py_TYPE(myself));
|
||||
StgDictObject *item_dict = PyType_stgdict(item_type);
|
||||
|
||||
if (view == NULL) return 0;
|
||||
|
||||
|
@ -2747,12 +2769,7 @@ static int PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags)
|
|||
view->format = dict->format ? dict->format : "B";
|
||||
view->ndim = dict->ndim;
|
||||
view->shape = dict->shape;
|
||||
view->itemsize = self->b_size;
|
||||
if (view->itemsize) {
|
||||
for (i = 0; i < view->ndim; ++i) {
|
||||
view->itemsize /= dict->shape[i];
|
||||
}
|
||||
}
|
||||
view->itemsize = item_dict->size;
|
||||
view->strides = NULL;
|
||||
view->suboffsets = NULL;
|
||||
view->internal = NULL;
|
||||
|
|
Loading…
Reference in New Issue