Skip to content

BUG: Cannot convert ctypes struct into numpy array #10528

@eric-wieser

Description

@eric-wieser

This seems like a bug inherited from ctypes, so maybe we need a workaround:

Start off with a very simple struct:

class foo(ctypes.Structure):
    _fields_ = [('a', ctypes.c_uint8), ('b', ctypes.c_uint32)]
f = foo()

We'd expect this to insert padding, and it does:

>>> memoryview(f).itemsize  # ok
8

But that padding doesn't show up in the format string:

>>> memoryview(f).format
'T{<B:a:<I:b:}'

The docs for struct say that

No padding is added when using non-native size and alignment, e.g. with ‘<’, ‘>’ "

So this format has size 5, which contradicts itemsize.

Sure enough, we catch this in our PEP3118 parser:

>>> np.array(f)
RuntimeWarning: Item size computed from the PEP 3118 buffer format string does not match the actual item size.
Out[45]: array(<__main__.foo object at 0x7f2715469bf8>, dtype=object)

I suspect there's already an issue for this - perhaps we need a PEP3118 tag.

The fix would be to special case ctypes objects in the array constructor, and not call memoryview on them because it doesn't actually work.


Worse yet, numpy doesn't stand a chance with an unpadded struct:

class foo(ctypes.Structure):
    _fields_ = [('a', ctypes.c_uint8), ('b', ctypes.c_uint32)]
    _pack_ = 1
f = foo()
>>> memoryview(f).itemsize  # ok
5
>>> memoryview(f).format  # WAT
'B'

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions