mirror of
https://github.com/python/cpython.git
synced 2025-10-03 21:55:41 +00:00
[3.11] gh-76963: PEP3118 itemsize of an empty ctypes array should not be 0 (GH-5576) (GH-100452)
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.
(cherry picked from commit 84bc6a4f25
)
Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
This commit is contained in:
parent
1fa4c6bd1f
commit
f6fe4bb75c
3 changed files with 30 additions and 8 deletions
|
@ -176,7 +176,9 @@ native_types = [
|
||||||
## arrays and pointers
|
## arrays and pointers
|
||||||
|
|
||||||
(c_double * 4, "<d", (4,), c_double),
|
(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 * 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, "&<" + s_short, (2,), POINTER(c_short)),
|
||||||
(POINTER(c_short) * 2 * 3, "&<" + s_short, (3,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)),
|
(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.
|
|
@ -2775,11 +2775,33 @@ static PyMemberDef PyCData_members[] = {
|
||||||
{ NULL },
|
{ 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;
|
CDataObject *self = (CDataObject *)myself;
|
||||||
StgDictObject *dict = PyObject_stgdict(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;
|
if (view == NULL) return 0;
|
||||||
|
|
||||||
|
@ -2792,12 +2814,7 @@ static int PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags)
|
||||||
view->format = dict->format ? dict->format : "B";
|
view->format = dict->format ? dict->format : "B";
|
||||||
view->ndim = dict->ndim;
|
view->ndim = dict->ndim;
|
||||||
view->shape = dict->shape;
|
view->shape = dict->shape;
|
||||||
view->itemsize = self->b_size;
|
view->itemsize = item_dict->size;
|
||||||
if (view->itemsize) {
|
|
||||||
for (i = 0; i < view->ndim; ++i) {
|
|
||||||
view->itemsize /= dict->shape[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
view->strides = NULL;
|
view->strides = NULL;
|
||||||
view->suboffsets = NULL;
|
view->suboffsets = NULL;
|
||||||
view->internal = NULL;
|
view->internal = NULL;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue