Re: Callback help

Robert Bradshaw <[email protected]> Wed, 21 Apr 2010 04:35:49 -0700
Newsgroups gmane.comp.python.pyrex
Message-ID <[email protected]>
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 =3D <void *>f
>
> my_cheese_data.py_data =3D <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 =3D <void
> *>cheese_data.py_callback
>    user_data =3D <void
> *>cheese_data.py_data
>       (<object>f)(name, user_data)
>
>
>
>
> _______________________________________________
> Pyrex mailing list
> [email protected]
> http://lists.copyleft.no/mailman/listinfo/pyrex