[Pyrex] Pyrex and char *x[]
Matt Hammond
matt.hammond at rd.bbc.co.uk
Wed May 16 08:33:29 UTC 2007
On Wed, 16 May 2007 06:29:41 +0100, Georg Grabler <ggrabler at gmail.com>
wrote:
> Hello everybody.
>
> I want an array to be passed to a function, so basically i started the
> function as follows:
>
> def addToList (self, char *array[]):
> ....
>
> This throws an error compiling:
> "Cannot convert Python object argument to type 'char(*(*))'"
Functions and classes defined python style (without a "cdef" prefix) are
made available to python and therefore can only deal with python objects -
which c-style arrays are not. Similarly c-style strings are not the same
as python strings.
Could you give a simple example of how you would use addToList from
python? Would you be passing it something like a list or tuple, or using a
library defined specialist array type?
Assuming you'd be passing it a list/tuple, eg:
items=["hello","doctor","yesterday","tomorrow","continue"]
X.addToList(items)
There is also the complication, since you're dealing with strings, of
handling garbage collection issues: if you don't copy the string data out
of the python string object, you need to inform python that you're still
using that object, otherwise it may get garbage collected and the storage
containing the string might be re-used!
Of course, the simplest, though not necessarily most efficient, solution
is to copy the string data out of the string into a newly allocated
character array.
If you want to declare c datatypes, or functions with c datatype
arguments, then they need to be prefixed with cdef; and they will not be
accessible from python (the specific variables, functions or classes
declared with cdef)
Here's roughly what I end up doing (in the .pyx file):
cdef extern from "string.h":
cdef void *memcpy(void *, void *, int)
class MyClass:
def addToList(self, listitems):
cdef char *cString
cdef char *copy
cdef int length
for pyString in listitems:
cString = pyString # pyrex auto converts
length = len(pyString)
# now make our own copy of the string data
copy = memcpy(copy, cString, length)
self.addList(copy)
cdef addList(self, char *str):
# your code
Caveat: I've not tested this code above; but as I said, I've found this
general approach works for me.
Remember python string's don't use null termination conventions, so if
you're retrieving them from your list for later use, you probably also
need to store the length of the string somewhere too. Hope that's not
teaching you to suck eggs :-)
Hope this helps
Matt
--
| Matt Hammond
| Research Engineer, FM&T, BBC, Kingswood Warren, Tadworth, Surrey, UK
| http://kamaelia.sf.net/
| http://www.bbc.co.uk/rd/
More information about the Pyrex
mailing list