[Pyrex] Callback help

Robert Bradshaw robertwb at math.washington.edu
Wed Apr 21 13:35:49 CEST 2010


On Apr 20, 2010, at 1:20 PM, Dale Cieslak wrote:

> Hi all,
>
> I apologize if this has already been answered or if it's a dumb  
> question...I tried looking through the archives and haven't found
> anything similar so far.  I'm trying to wrap a C API that makes use of
> callbacks, and I looked at the cheesefinder callback demo code in the
> Pyrex distribution.  If I write my code to match the cheesefinder
> example, it works fine.  However, it appears that the cheesefinder
> example passes the Python function pointer as the user_data itself,  
> but
> what if I want to ALSO pass user data to my Python callback?   I  
> should
> point out that it's been several years since I did any serious C  
> coding
> (which is why I'm trying to wrap the thing in Python), so I'm hoping
> it's just a simple n00b-level  solution.   I tried various  
> permutations
> of using PyCObject_AsVoidPtr instead of just casts, but to no avail.
> Essentially it compiles fine, but Bus Errors/Seg Faults when it goes  
> to call the python callback.

If you're casting Python objects to void*, you need to make sure  
you're holding onto a reference of them elsewhere (e.g. as an object,  
in a list, ...). Otherwise they'll be garbage collected and the void*  
you stored will become meaningless (hence the segfaults).

> Here's the gist of what I tried.
>
> Thanks in
> advance,
> Dale
>
> cdef extern from "cheesefinder.h":
>
> ctypedef void (*cheesefunc)(char *name, void *user_data)
>    void
> find_cheeses(cheesefunc user_func, void *user_data)
>
> ctypedef
> struct my_cheese_data:
>       void *py_callback
>       void
> *py_data
>
> def find(f, data):
>    cdef my_cheese_data user_data
>    my_cheese_data.py_callback = <void *>f
>
> my_cheese_data.py_data = <void *>data
>
>
> find_cheeses(super_callback, <void*>&user_data)
>
> cdef void callback(char *name, void *f):
>    (<object>f)(name)
>
> cdef void super_callback(char *name, void *cheese_data):
>    cdef void *f
>    cdef void *user_data
>
>    f = <void
> *>cheese_data.py_callback
>    user_data = <void
> *>cheese_data.py_data
>       (<object>f)(name, user_data)
>
>
>
>
> _______________________________________________
> Pyrex mailing list
> Pyrex at lists.copyleft.no
> http://lists.copyleft.no/mailman/listinfo/pyrex




More information about the Pyrex mailing list