[Pyrex] Functions pointers
Robert Bradshaw
robertwb at math.washington.edu
Fri Apr 11 12:00:25 CEST 2008
On Apr 11, 2008, at 2:58 AM, Daniele Pianu wrote:
> I've correct the pyrex code
>
> -------- funcs.pyx --------
> cdef extern from "c_funcs.h":
> int callFoo(int(*)(int), int)
> int callBar(int(*)(int*), int*)
> char* callFooBar(char*(*)(char*), char*)
>
> cdef class funcs:
> cdef object funcsDict
> def __init__(self):
> cdef unsigned long fooPointer
> fooPointer = <unsigned long>&callFoo
Shouldn't you be taking the address of returnFoo here?
>
> self.funcsDict = {}
> self.funcsDict['returnFoo'] = fooPointer
>
> def pyCallFoo(self, foo):
> cdef unsigned long tmp
> tmp = self.funcsDict['returnFoo']
> return callFoo(<int(*)(int)>tmp, foo)
>
>
> But it gives me a segmentation fault again... :(
>
>
> 2008/4/11, Robert Bradshaw <robertwb at math.washington.edu>:
> On Apr 11, 2008, at 2:12 AM, Daniele Pianu wrote:
> I'm trying to wrap a C function that requires a C function pointer
> as argument. I've wrote a pyrex extension with a dictionary where
> every key is a C function name, and every entry is a C function
> pointer, stored as a long. I call the C function from python
> passing the function name and the necessary data.
>
> An example:
>
> -------- c_funcs.h ---------
>
> int returnFoo(int);
>
> int returnBar(int*);
>
> char* returnFooBar(char*);
>
> int callFoo(int(*)(int), int);
>
> int callBar(int(*)(int*), int*);
>
> char* callFooBar(char*(*)(char*), char*);
>
>
> ------- c_funcs.c -------
> #include <c_funcs.h>
>
> int returnFoo(int foo){
> return foo;
> }
>
> int returnBar(int* bar){
> if (bar)
> return *bar;
> }
>
> char* returnFooBar(char* fooBar){
> if (fooBar)
> return fooBar;
> }
>
> int callFoo(int(*func)(int), int foo){
> return (*func)(foo);
> }
>
> int callBar(int(*func)(int*), int* bar){
> return (*func)(bar);
> }
>
> char* callFooBar(char*(*func)(char*), char* FooBar){
> return (*func)(FooBar);
> }
>
> ------- funcs.pyx ----------
> cdef extern from "c_funcs.h":
> int callFoo(int(*)(int), int)
> int callBar(int(*)(int*), int*)
> char* callFooBar(char*(*)(char*), char*)
>
> cdef class funcs:
> cdef object funcsDict
> def __init__(self):
> cdef unsigned long fooPointer
> fooPointer = <unsigned long>&callFoo
> self.funcsDict = {}
> self.funcsDict['returnFoo'] = fooPointer
> # Here the python interpreter prints an integer, not a long as
> expected!!!
>
> Python ints are c longs, which may not actually be the size of
> pointers on all systems.
>
> print self.funcsDict['returnFoo']
>
> def pyCallFoo(self, foo):
> # The call to C function produces a Segmentatio Fault
> return callFoo(<int(*)(int)>self.funcsDict['returnFoo'], foo)
>
> self.funcsDict['returnFoo'] returns a PyObject* (that points to a
> Python int), and it is the memory location of the object that you
> are casting to an int(*)(int).
>
> In Cython you can write
>
> return callFoo(<int(*)(int)><long>self.funcsDict['returnFoo'], foo)
>
> to force it to unpack the Python long. With in Pyrex you need an
> extra variable
>
> cdef long my_temp_var
> my_temp_var = self.funcsDict['returnFoo']
> return callFoo(<int(*)(int)>my_temp_var, foo)
>
> Just make sure no one messes with your dictionary!
>
>
>
>
> How can I solve the problem? Every advice about alternative
> implementation is also appreciated :)
>
>
>
>
> _______________________________________________
> Pyrex mailing list
> Pyrex at lists.copyleft.no
> http://lists.copyleft.no/mailman/listinfo/pyrex
More information about the Pyrex
mailing list