[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