[Pyrex] Functions pointers

Daniele Pianu muogoro at gmail.com
Fri Apr 11 11:58:07 CEST 2008


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
      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 :)
> >
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.copyleft.no/pipermail/pyrex/attachments/20080411/fe34d7ca/attachment.html 


More information about the Pyrex mailing list