[Numpy-discussion] Ctypes support in NumPy
Albert Strasheim
fullung at gmail.com
Sun Jul 2 10:24:36 EDT 2006
Hello all
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 [133]: printf = ctypes.cdll.msvcrt.printf
In [134]: printf.argtypes = [ctypes.c_char_p, ctypes.c_void_p]
In [135]: x = N.array([1,2,3])
In [136]: printf('%p\n', x.ctypes.data)
01CC8AC0
Out[136]: 9
In [137]: hex(x.__array_interface__['data'][0])
Out[137]: '0x1cc8ac0'
It would be nice if we could the _as_parameter_ magic to work as well. See
this thread:
http://aspn.activestate.com/ASPN/Mail/Message/ctypes-users/3122558
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:
func.argtypes[n].from_param(x._as_parameter_)
However, if I try passing x directly to printf, I get this:
In [147]: printf('%p\n', x)
...
ArgumentError: argument 2: exceptions.TypeError: wrong type
However, this much works:
In [148]: ctypes.c_void_p.from_param(x._as_parameter_)
Out[148]: <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 [167]: ctypes.POINTER(ctypes.c_double).from_param(x._as_parameter_)
...
TypeError: expected LP_c_double instance instead of int
But this works:
In [168]: ctypes.POINTER(ctypes.c_double).from_address(x._as_parameter_)
Out[168]: <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.
Regards,
Albert
More information about the NumPy-Discussion
mailing list