C API function callbacks into C++ member function code

谁都会走 提交于 2019-11-28 11:08:08

You cannot directly pass a member function. A member function has the implicit parameter this and C functions don't.

You'll need to create a trampoline (not sure the signature of the callback, so just doing something random here).

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

One issue is where does that object pointer come from. Hopefully, fmod gives you a generic context value that will be provided to you when your callback is made (you can then pass in the object pointer).

If not, you'll just need to make it a global to access it.

I guess it supposed to work like this:
You can assign some user data to channel by calling FMOD_Channel_SetUserData. This user data should be a pointer to your C++ object that handles events. Then you should write C-style callback that extracts that object by calling FMOD_Channel_GetUserData and then calls your C++ instance method on that object.

There is a non-portable, and pretty hackish solution that has the advantage of at least being thread-safe, which the "trampoline" methods are not.

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

It's messy, and you'll have to provide an implementation for any new platform (any time the calling convention changes), but it works, is thread-safe. (Of course you'll also have to watch out for DEP). The other thread-safe solution is to resort to thread-local storage (assuming that you know the call-back will happen on the same thread as the call you made).

See http://www.codeproject.com/KB/cpp/GenericThunks.aspx for an example of how you could go about generating thunks.

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

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

you need to use a trampoline and store the pointer to the object you want to get the member function called on in a global or static variable, i.e.

Object *x;
void callback_trampoline() { x->foobar(); }
...
FMOD_Channel_SetCallback(CHANNEL, callback_trampoline);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!