Description
Original ticket http://projects.scipy.org/numpy/ticket/2079 on 2012-03-13 by trac user pieleric, assigned to unknown.
The latest version of numpy supports numpy.ctypeslib.as_array() for a ctypes.POINTER. However, when using numpy.ctypeslib.as_array() on a pointer multiple times in a row with different shapes, it's always the shape of the first call which is used.
Example:
import ctypes
import numpy
>>> buffer = ctypes.pointer((ctypes.c_uint16 * 100)())
>>> p = ctypes.cast(buffer, ctypes.POINTER(ctypes.c_uint16))
>>> a = numpy.ctypeslib.as_array(p, shape=(100,))
>>> a.shape
(100,)
>>> b = numpy.ctypeslib.as_array(p, shape=(10,10))
>>> b.shape
(100,)
We would expect b.shape == (10,10) .
The bug is in as_array() and prep_pointer(). They are too much a copy-paste of the case of an ndarray: only create the array_interface if it is not yet there. For an ndarray this works fine as the array_interface is saved on the type. For a pointer, it should be updated every time.
So, I propose something like this:
def prep_pointer(pointer_obj, shape):
contents = pointer_obj.contents
dtype = _dtype(type(contents))
inter = {'version': 3,
'typestr': dtype.str,
'data': (ct.addressof(contents), False),
'shape': shape}
pointer_obj.__array_interface__ = inter
def as_array(obj, shape=None):
if hasattr(obj, 'contents'):
prep_pointer(obj, shape)
else:
tp = type(obj)
try: tp.__array_interface__
except AttributeError: prep_array(tp)
return array(obj, copy=False)
BTW, the description of as_array() should be updated to mention the "shape" parameter instead of the "size" parameter.