[Numpy-discussion] Ctypes support in NumPy
fullung at gmail.com
Sun Jul 2 09:24:36 CDT 2006
Travis Oliphant wrote:
> I've been playing a bit with ctypes and realized that with a little
> help, it could be made much easier to interface with NumPy arrays.
> Thus, I added a ctypes attribute to the NumPy array. If ctypes is
> installed, this attribute returns a "conversion" object otherwise an
> AttributeError is raised.
> The ctypes-conversion object has attributes which return c_types aware
> objects so that the information can be passed directly to c-code (as an
> integer, the number of dimensions can already be passed using c-types).
> The information available and it's corresponding c_type is
> data - c_void_p
> shape, strides - c_int * nd or c_long * nd or c_longlong * nd
> depending on platform
I did a few tests and this seems to work nicely:
In : printf = ctypes.cdll.msvcrt.printf
In : printf.argtypes = [ctypes.c_char_p, ctypes.c_void_p]
In : x = N.array([1,2,3])
In : printf('%p\n', x.ctypes.data)
In : hex(x.__array_interface__['data'])
It would be nice if we could the _as_parameter_ magic to work as well. See
If I understood Thomas correctly, in the presence of argtypes an an
instance, say x, with _as_parameter_, the following is done to convert the
instance to something that the function accepts as its nth argument:
However, if I try passing x directly to printf, I get this:
In : printf('%p\n', x)
ArgumentError: argument 2: exceptions.TypeError: wrong type
However, this much works:
In : ctypes.c_void_p.from_param(x._as_parameter_)
Out: <cparam 'P' (01cc8ac0)>
So I don't understand why the conversion isn't happening automatically.
Another quirk I noticed is that non-void pointers' from_param can't seem to
be used with ints. For example:
In : ctypes.POINTER(ctypes.c_double).from_param(x._as_parameter_)
TypeError: expected LP_c_double instance instead of int
But this works:
In : ctypes.POINTER(ctypes.c_double).from_address(x._as_parameter_)
Out: <ctypes.LP_c_double object at 0x01DCE800>
I don't think this is too much of an issue though -- you could wrap all your
functions to take c_void_ps. If you happen to pass an int32 NumPy array to a
function expecting a double*, you might run into problems though.
Maybe there should be a way to get a pointer to the NumPy array data as a
POINTER(c_double) if it is known that the array's dtype is float64. Ditto
for c_int/int32 and the others.
More information about the Numpy-discussion