[Pyrex] Re: callback

Pedro Rodriguez pedro_rodriguez at club-internet.fr
Mon Aug 18 12:48:07 CEST 2003


On Mon, 18 Aug 2003 03:04:40 +0000, Bryan Weingarten wrote:

> i currently have a callback similar to the cheese demo.  but i have a
> problem i hope someone can help me resolve.
> 
> 
> the following code works correctly... it's basically the "cheese" code:
> 
> class Play:
>     def status_callback(self, callback):
>         set_status_callback(self.ctx, _callback_wrapper, <void*>callback)
> 
> cdef int _callback_wrapper(void *callback, long sec, long msec):
>     return (<object>callback)(sec, msec)
> 
> 
> my problem is that the i need user data to be passed into status_callback
> which gets passed back to the python callback.  the "cheese" way of doing
> this is to cast the python callback function to a void* and pass it into the
> user data field of the c function.  unfortunately, this takes up the one and
> only user data field and doesn't allow for the python user to pass in user
> data.  i tried to add the _callback_wrapper as a method of the class so i
> could save the data as instance data, but pyrex complained about that... so
> i'm at a loss now...  can someone help me?
> 

Instead of just passing the actual python callback, you can pass a python
object that will hold all the data you need. 

Example using a tuple object:

class Play:
    def status_callback(self, callback, user_data):
        data = (callback, user_data)
        set_status_callback(self.ctx, _callback_wrapper, <void*>data)

cdef int _callback_wrapper(void *data, long sec, long msec):
    callback, user_data = <object>data
    return callback(user_data, sec, msec)


But there may be still an issue here. I don't know if the 'data' tuple
provided to the C code (set_status_callback) may be garbage collected.
In that case, it may be required to prevent this by memorizing the last
passed data at global level.

data = None

class Play:
    def status_callback(self, callback, user_data):
        global data
        data = (callback, user_data)
        set_status_callback(self.ctx, _callback_wrapper, <void*>data)

cdef int _callback_wrapper(void *data, long sec, long msec):
    callback, user_data = <object>data
    return callback(user_data, sec, msec)

HTH,

-- 
Pedro





More information about the Pyrex mailing list