[Numpy-discussion] Ctypes support in NumPy

Travis Oliphant oliphant.travis at ieee.org
Mon Jul 3 02:14:05 EDT 2006


Albert Strasheim wrote:
> 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_)
>   
Unfortunately, from the source code this is not true.  It would be an 
improvement, but the source code shows that the from_param of each type 
does something special and only works with particular kinds of 
data-types --- basic Python types or ctypes types.  I did not see 
evidence that the _as_parameter_ method was called within any of the 
from_param methods of _ctypes.c
> 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.
>   
Despite any advertisement, the code is just not there in ctypes to do it 
when argtypes are present.   Dealing with non-ctypes data is apparently 
not handled when argtypes are present.   Get-rid of the argtypes setting 
and it will work (because then the _as_parameter_ method is called....

> Another quirk I noticed is that non-void pointers' from_param can't seem to
> be used with ints. For example:
>   
Yeah from the code it looks like each from_param method has it's own 
implementation that expects it's own set of "acceptable" things.  There 
does not seem to be any way for an object to inform it appropriately.
> 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.
>   
Yeah, but you were going to run into trouble anyway.  I don't really see 
a lot of "value-added" in the current  type-checking c-types provides 
and would just ignore it at this point.  Build a Python function that 
calls out to the c-function. 
> 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.
>   

I could see value in

arr.ctypes.data_as()
arr.ctypes.strides_as()
arr.ctypes.shape_as()

methods which allow returning the data as different kinds of c-types 
things instead of the defaults --- Perhaps we just make data, strides, 
and shapes methods with an optional argument.

-Travis





More information about the NumPy-Discussion mailing list