pyFMOD writing a callback function in Python

Thomas Heller theller at python.net
Thu Feb 10 13:21:25 EST 2005


Marian Aldenhövel <marian at mba-software.de> writes:

> Hi,
>
> I am using the FMOD audio-library with the pyFMOD python bindings. pyFMOD uses
> ctypes.

I was looking into this recently, because another poster also asked
about pyFMOD: which FMOD version do you use?  I was only able to find
fmodapi374.zip (for windows), and that version doesn't seem to work with
the pyFMOD release I found.

> It is possible to register callback functions with FMOD that are
> called at certain points in the processing pipeline or when certain events
> happen.
>
> I am expecially interested in the one that fires when a currently playing
> stream ends. This is what the declaration in pyFMOD looks like:
>
>    _FSOUND_Stream_SetEndCallback =
>       getattr(fmod,"_FSOUND_Stream_SetEndCallback at 12")
>    _FSOUND_Stream_SetEndCallback.restype = c_byte
>    def FSOUND_Stream_SetEndCallback(stream, callback, userdata):
>       result = _FSOUND_Stream_SetEndCallback(c_int(stream), c_int(callback),
>                                              c_int(userdata))
>       if not result: raise fmod_exception()
>
> I cannot make it work, however. I tried:
>
>    def _sound_end_callback(stream,buf,len,userdata):
>      print "_sound_end_callback(): Stream has reached the end."
>
> as simplest possible callback function. I am registering it like this:
>
>    pyFMOD.FSOUND_Stream_SetEndCallback(_currenttrack,_sound_end_callback,0)
> 				
> And this is how my program dies:
>
>    File "d:\projekte\eclipse\workspace\gettone\gettonesound.py", line
>    175, in sound_tick
>      pyFMOD.FSOUND_Stream_SetEndCallback(_currenttrack,_sound_end_callback,0)
>    File "c:\programme\Python23\lib\site-packages\pyFMOD.py", line 690,
>    in FSOUND_Stream_SetEndCallback
>      result = _FSOUND_Stream_SetEndCallback(c_int(stream),
>      c_int(callback), c_int(userdata))
> TypeError: int expected instead of function instance

The first problem is that the FSOUND_Stream_SetEndCallback function, as
given, converts all parameters to integers.
Second, you cannot pass a Python function directly as callback, you have
to create a function prototype first which specifies calling convention,
return type, and argument types.
Third, you instantiate the prototype with a Python callable, which
creates the C callable callback function, and use that in the
FSOUND_Stream_SetEndCallback call.
All in all, it should look similar (I can't test it!) to this code:

_FSOUND_Stream_SetEndCallback = getattr(fmod,"_FSOUND_Stream_SetEndCallback at 12")
_FSOUND_Stream_SetEndCallback.restype = c_byte
def FSOUND_Stream_SetEndCallback(stream, callback, userdata):
   result = _FSOUND_Stream_SetEndCallback(c_int(stream), callback,
                                          c_int(userdata))
   if not result: raise fmod_exception()

# from the FMOD header file:
##typedef signed char (F_CALLBACKAPI *FSOUND_STREAMCALLBACK)
##  (FSOUND_STREAM *stream, void *buff, int len, void *userdata);

# funtion prototype
FSOUND_STREAMCALLBACK = WINFUNCTYPE(c_char, c_int, c_void_p, c_int, c_void_p)

# create callback function
callback_function = FSOUND_STREAMCALLBACK(_sound_end_callback)

# and then put it to work:

FSOUND_Stream_SetEndCallback(stream, callback_function, userdata)


You should also be aware that you have to keep the callback_function
object alive *as long as the FMOD library is using it*!  If you don't,
it will probably crash.

> I am very new to Python and have zero idea what the problem is nor how to
> solve it. In some of my other languages I would have to explicitly make a
> function pointer and possibly have to cast that to an int to pass it to
> SetEndCallback, but that seems very inappropriate in Python...

Thomas



More information about the Python-list mailing list