10000 bpo-32782: PEP3118 itemsize of an empty ctypes array should not be 0 by eric-wieser · Pull Request #5576 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-32782: PEP3118 itemsize of an empty ctypes array should not be 0 #5576

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Dec 23, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
bpo-32782: PEP3118 itemsize of an empty ctypes array should not be 0
The itemsize returned in a memoryview of a ctypes array should be computed from the item type, not by dividing the total size by the length and assuming that the length is not zero.
  • Loading branch information
eric-wieser committed Jun 6, 2019
commit f4e3ca9ad1735fba4f85d828ed4e99f6ac8557df
2 changes: 2 additions & 0 deletions Lib/ctypes/test/test_pep3118.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,9 @@ class Complete(Structure):
## 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)),
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
49 changes: 42 additions & 7 deletions Modules/_ctypes/_ctypes.c
8000
Original file line number Diff line number Diff line change
Expand Up @@ -2596,11 +2596,47 @@ static PyMemberDef PyCData_members[] = {
{ NULL },
};

static int PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags)
/*
Get the StgDictObject corresponding to a single item of a multidimensional
array.
Takes and returns a borrowed reference.
*/
static StgDictObject *
PyCData_item_stgdict(StgDictObject *dict)
{
if (dict->ndim == 0) {
/* scalar is its own item */
return dict;
}
else {
/* follow _type_, eliminating a dimension */
PyObject *type_attr;
StgDictObject *item_dict;

type_attr = PyDict_GetItemString((PyObject *)dict, "_type_");
if (!type_attr) {
PyErr_SetString(PyExc_AttributeError,
"class must define a '_type_' attribute");
return NULL;
}

item_dict = PyType_stgdict(type_attr);
if (!item_dict) {
PyErr_SetString(PyExc_TypeError,
"_type_ must have storage info");
return NULL;
}

return PyCData_item_stgdict(item_dict);
}
}

static int
PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags)
{
CDataObject *self = (CDataObject *)myself;
StgDictObject *dict = PyObject_stgdict(myself);
Py_ssize_t i;
< 8A43 /td> StgDictObject *item_dict;

if (view == NULL) return 0;

Expand All @@ -2613,12 +2649,11 @@ 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];
}
item_dict = PyCData_item_stgdict(dict);
if (item_dict == NULL) {
return -1;
}
view->itemsize = item_dict->size;
view->strides = NULL;
view->suboffsets = NULL;
view->internal = NULL;
Expand Down
0