C API Function Calls Callbacks to C ++ Member Function Code

So, I am using the FMOD api, and it is really a C api.

Not that it's bad or something else. Its just that it doesnโ€™t interact well with C ++ code.

For example, using

FMOD_Channel_SetCallback( channel, callbackFunc ) ; 

He wants a C-style function for callbackFunc , but I want to pass her a member function of the class.

I ended up using the Win32 trick, making it a static function. Then it works as a callback in FMOD.

Now I need to crack my code to make some of them static, just to take into account FM-C Cess.

I wonder if this is possible in FMOD, or if there is a connection, to associate a callback with a specific function of a member of an instance of a C ++ object (and not a static function). That would be much smoother.

+9
c ++ c fmod
Mar 10 '10 at 20:30
source share
5 answers

You cannot pass a member function directly. A member function has an implicit parameter this and C functions do not.

You need to create a trampoline (not sure what the callback signature is, so just do something random here).

 extern "C" int fmod_callback( ... args ...) { return object->member(); } 

One problem is where the object pointer comes from. We hope that fmod will provide you with the general context value that will be provided to you in the callback (you can pass an object pointer).

If not, you just need to make it global in order to access it.

+11
Mar 10 '10 at 20:36
source share

I assume that it should work as follows:
You can assign some user data to a channel by calling FMOD_Channel_SetUserData . This user data should be a pointer to your C ++ object that processes events. Then you must write a C-style callback that retrieves this object by calling FMOD_Channel_GetUserData , and then calls your C ++ instance method for that object.

+4
Mar 10
source share

There is an intolerable and rather hacky solution that has the advantage of at least being thread safe, that trampoline methods are not.

You can generate the actual machine function code on the fly. The basic idea is that you have a template for your callback function that takes a pointer to an object and a pointer to a member function and gives you a heap memory block that you can pass to the library as a C callback function, which will be, when called, expand and call a member function on this object.

This is messy, and you will have to provide an implementation for any new platform (anytime the calling convention changes), but it works, is thread safe. (Of course, you will also have to keep track of the DEP). Another thread-safe solution is to resort to a local thread store (provided that you know that the callback will occur in the same thread as the call you made).

See http://www.codeproject.com/KB/cpp/GenericThunks.aspx for an example of how you might start generating tricks.

+2
Mar 10 '10 at 21:09
source share

Using only a function pointer (and no additional separate object pointer) for the C callback is a broken design, in my humble opinion.

If the function were FMOD_Channel_SetCallback(channel, callbackFunc, callbackObj) , then your static method just takes an instance of the object and then calls callbackObj->func() (which, obviously, can be unsteady).

+1
Mar 10 '10 at 20:36
source share

you need to use a trampoline and save a pointer to the object that you want to receive in the member function called in a global or static variable, i.e.

 Object *x; void callback_trampoline() { x->foobar(); } ... FMOD_Channel_SetCallback(CHANNEL, callback_trampoline); 
0
Mar 10 '10 at 20:38
source share



All Articles