[Numpy-discussion] Ctypes support in NumPy
Travis Oliphant
oliphant.travis at ieee.org
Mon Jul 3 01:50:56 EDT 2006
Albert Strasheim wrote:
> I did a few tests and this seems to work nicely:
>
Hey Albert, I read the post you linked to on the ctypes mailing list.
I hope I didn't step on any toes with what I did in NumPy. I was just
working on a ctypes interface and realized that a lot of the cruft to
convert to what ctypes was expecting could and should be handled in a
default way. The conversion of the shapes and strides information to
the "right-kind" of ctypes integer plus the inclusion of ctypes in
Python 2.5 was enough to convince me to put some kind of hook into the
array object. I decided to make the ctypes attribute return an object
so that the object could grow in the future additional attributes and/or
methods to make it easier to interface with ctypes.
I looked a bit at the source code and was disappointed to see that the
_as_parameter_ approach is pretty limited. While there is talk of
supporting a tuple return of _as_parameter_ in the source code comments,
there is no evidence in the source itself of supporting it.
There is also the changed way of handling additional arguments when
argtypes is set on the function which uses the from_param method.
Unfortunately, as Thomas responds to your post, the from_param method
must be on one of the ctypes to work. You have to add support
specifically for one of the c-data types.
I think the _as_parameter_ approach returning a tuple that could be
interpreted as the right ctype was better because it let other objects
play the ctypes game.
Basically, what you need is a type-map just like swig uses. But, now
that ctypes is in Python, it will be slower to change. That's a bit
unfortunate.
But, ultimately, it works fine now. I don't know what is really gained
by applying an argtypes to a function call anyway --- some kind of
"type-checking". Is that supposed to be safer.
For NumPy extension modules, type checking is only a small part of the
memory-violation danger. In-correct array bounds and/or striding is far
more common - not-to mention unaligned memory areas and/or unwriteable
ones (like a read-only memory-mapped file).
Thus, you're going to have to write a small "error-checking" code in
Python anyway that calls out to the C-library with the right
arguments. So, basically you write an extension module that calls
c-code just as you did before, but now the entire "extension" module can
all be in Python because the call to an arbitrary C-library is made
using ctypes.
For arrays, you will typically need to pass one or more of the data,
the dimension information, the stride information, and the number of
dimensions. The data-type will be known about because function calls
usually handle only a specific data-type. Thus, I started with a ctypes
object that produces this needed data in the format that ctypes needs,
so it can be very easy to use an array with the ctypes module.
Frankly, I'm quite impressed with the ease of accessing C-code available
using c-types. It quite rivals f2py in enjoyment using it.
One thing I like about c-types over Pyrex, for example is that it lets
you separate the C-code from the Python code instead of "mixing it all
together"
I wouldn't be surprised if c-types doesn't become the dominant way to
interface C/C++ and possibly even Fortran code (but it has tougher
competition in f2py) once it grows up a little with additional ease-of-use.
-Travis
More information about the NumPy-Discussion
mailing list