[Pyrex] Re: Re: callback
Pedro Rodriguez
pedro_rodriguez at club-internet.fr
Tue Aug 19 13:15:31 CEST 2003
>
> john, pedro,
>
> thanks for your quick responses... i'm still having trouble with both of
> your suggestions.
>
>
> 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 # this is line 56
> return callback(data, sec, msec)
>
> when i compile this i get the following error
> C:\src>mpgedit.pyx:56:20: Cannot convert 'void (*)' to Python object
>
> when i use the global variable technique as pedro suggested i get an
> additional error
> C:\src>mpgedit.pyx:49:8: '%s' redeclared
> C:\src>mpgedit.pyx:55:20: Cannot convert 'void (*)' to Python object
>
> line 49 is the "global data" line
>
I don't understand where those errors come from. The following standalone
code compiles just fine for me. My setup is :
redhat 7.3
python 2.2.2
pyrex 0.8.2
and the commands I used:
pyrexc t.pyx
gcc -g -c -fPIC -I/mnt/wrk/python/include/python2.2 t.c
gcc -g -shared t.o -lm -o t.so
# pyrex code
cdef extern from "../playif.h":
ctypedef int (*status)(void *, long, long)
void set_status_callback(int, status, void*)
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)
/* ../playif.h */
typedef int (*status)(void *, long, long);
void set_status_callback(int, status, void*);
>
> john,
>
> i would prefer to use your Py_INCREF and Py_DECREF since i'm used to using
> that when i write extesions manually. but i don't see how use it in my
> case. in my example, i don't see where to Py_INCREF or Py_DECREF.
>
I hope you, John and Greg will correct me if I am wrong. Each time you
pass a python object that will be kept inside the C library, you'll
have to call Py_INCREF. In your first code, this will have to be done
on the callback, prior to set_status_callback. If you use Greg's hint
with an instance method, this may even more necessary since your object
may get garbage collected (question : is Py_INCREF on an instance method
sufficient to prevent the actual instance to be freed ?).
For the Py_DECREF call, it will mostly depends on the way the C library
releases the object passed. Your api 'set_status_callback' doesn't seem
to return the former object passed, so this means that you'll have to
do the tracking yourself (if it were returned, you just will have to do
a Py_DECREF on the returned value).
This is why I used the global value approach. I do the tracking at
Python's level, and this tracking mirrors the C library content. No need
to do Py_INC/DEC REF, since Python does it already.
There is still one last issue. In my example, once called the C library
will alway keep a Python object. If possible/necessary, a special case
should be considered. If removing the callback consists in just passing
a NULL pointer, it may be necessary to test if python's callback is None
and passing NULL in this case.
Hoping I am not on the wrong track...
--
Pedro
mirors the
More information about the Pyrex
mailing list