C API function callbacks into C++ member function code - c++

So, I'm using the FMOD api and it really is a C api.
Not that that's bad or anything. Its just it doesn't interface well with C++ code.
For example, using
FMOD_Channel_SetCallback( channel, callbackFunc ) ;
It wants a C-style function for callbackFunc, but I want to pass it a member function of a class.
I ended up using the Win32 trick for this, making the member function static. It then works as a callback into FMOD.
Now I have to hack apart my code to make some of the members static, just to account for FMOD's C-ness.
I wonder if its possible in FMOD or if there's a work around to link up the callback to a specific C++ object's instance member function (not a static function). It would be much smoother.

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);

Related

C Library Callback in C++ without pointer to "this"

I have a C library here which I want to wrap in a C++ class. The library works asynchronous and needs to set an error handler. I know how to wrap an error handler in a static class function for a C library, but I am used to having something like a void *user_data pointer, where I can put this in to call a member function from the static thunk.
Is there a way to register the callback for a member function directly, as this library does not feature a pointer to some userdata?
You can wrap it in your own static function which is aware of some global (or static local) object on which it is to operate. You can even make this function a static method if want, but you can't call a method on an object without supplying an object on which it is to be called.
Edit : having thought about it for a while, maybe there is a way. You can essentially emulate thread-local storage by having a global collection of collections of states indexed by thread id. Within each thread-bound collection of states you can keep a stack/queue (depending on how the data are processed) of calling objects. The callback can look up the stored queue (because the callback knows the thread id in which it is running). This would allow you to force a single-threaded framework to operate on multiple streams of data.

Callback concept and normal calling

I'm so confused
we know that all functions defined as global so we can call and use any function inside any block without passing it as argument
why we use Function callback concept while we can use a function inside any function without passing it
so why we use callback concept ?
For the same reason you use variables instead of constants.
Passing a callback to a function allow that function to call a different callback depending on how it was called.
Calling a function by name inside a function will always call that one function.
The call back concept means to provide some other function with a function to call when it needs something to be done, e.g. when an event happens. It also often means we can change the function to be called in run-time.
In this way, the knowledge of when to call what is not needed by the calling function. For example, a 3rd party library defines callbacks for the user's program to "plug-in" functionality into the library, or to be called when an event occurrs, a state is reached or an error occurrs and the library needs to know what to do about the error.
This is just a simple answer. Google around to find more information and see https://en.wikipedia.org/wiki/Callback_(computer_programming)

wxWidgets wxFileSystemHandler::OpenFile() never gets called

I extended the class wxFileSystemHandler to handle special protocols I use in my application. My implementation of wxFileSystemHandler::CanOpen() is called, recognizes the protocol and returns TRUE. But my implementation of wxFileSystemHandler::OpenFile() never gets called. I inspected the wxWidgets code and saw that the CanOpen() member function is called by the pointer that I registered. But when a call to OpenFile() is made they pass the pointer to a wxFileSystem::MakeLocal() member function that tries to get another pointer inside a hash map that, obviously, is not my instance.
Someone got a problem like this before?
Not sure what exactly are you doing, i.e. when do you expect your handler to be called, but in any case MakeLocal() is supposed to create a new instance of the same class if you mark the object as being dynamically creatable using wxRTTI macros and use the object as given otherwise. So if you really need the same object to be reused, you probably need to use wxDECLARE_ABSTRACT_CLASS() in its class. But OTOH why is it a problem to make a new instance?

Member pointers or reference arguments?

I have the following problem.
I got a class PluginLoader which oversees loading of plugins. It divides sub-stages of work to other classes like Plugin. Plugin calls functions of PluginLoader in its processing. Let's call that function AddData. Here, PluginLoader has to check if the data it receives is duplicate. For that, it uses a ConflictResolver class. Now, my problem is how to make an object of ConflictResolver available to PluginLoader. There are 3 ways I see out of this.
Use a ConflictResolverFactory class and create an object of ConflictResolver for PluginLoader.
Pass a constructed ConflictResolver* to the PluginLoader via its constructor or a member function SetConflictResolver and store it in a member variable and use it later. Both ways have drawbacks. If I pass it in the constructor, I will have to throw if the pointer is NULL. And I can't use exceptions as it is the custom here. If I pass it via SetConflictResolver, there is no way that I can guarantee that that function will be actually called by the user. Or I will have to check whether the member ConflictResolver* is NULL everywhere I use it.
Pass a ConflictResolver & to PluginLoaders Load method where all the work will be done. In turn, Plugins Load method has to accept a ConflictResolver & as well (though it has no use for it) and pass that back to AddData where PluginLoader will be able to use it.
Third method is safer compared to second. However, I have to pass around a reference even when it is not used.
If the first method cannot be used, what is the best way to do this?
Apologies for the wall :wq!
You could pass a ConflictResolver& to the PluginLoader constructor. You can now guarantee that the object is not null.

how to pass a non static-member function as a callback?

io_iterator_t enumerator;
kern_return_t result;
result = IOServiceAddMatchingNotification(
mNotifyPort,
kIOMatchedNotification,
IOServiceMatching( "IOFireWireLocalNode" ),
serviceMatchingCallback,
(void *)0x1234,
& enumerator );
serviceMatchingCallback((void *)0x1234, enumerator);
if i declare serviceMatchinCallback as static then it works, but i do not want it to be static. Is there a way to pass it a non-static callback function?
Thank you
The prototype for IOServiceMatchingCallback is not compatible with a non-static class method (and technically is not compatible with a static class method either), so you are not going to be able to use that.
But luckily IOServiceAddMatchingNotification supports a context pointer (or as they call it, a refCon) which will allow you to create a thunk that does not rely on global data.
You need to define a callback with compatible linkage (i.e. extern "C"). This function will cast your refCon to your object pointer and then forward the call to your instance method:
extern "C"
void io_callback(void *refcon, io_iterator_t iterator)
{
myclass *c = static_cast<myclass *>(refcon);
c->real_callback(iterator);
}
Then, when you call IOServiceAddMatchingNotification, make sure to pass a pointer to your object for refCon (here I'm assuming you call IOServiceAddMatchingNotification from a member function and you have a this pointer):
result = IOServiceAddMatchingNotification(
mNotifyPort,
kIOMatchedNotification,
IOServiceMatching( "IOFireWireLocalNode" ),
serviceMatchingCallback,
this,
&enumerator );
You could keep it static, but use the userdata to store the this pointer in addition to whatever other userdata you want (by packing them into a structure, for example) and then call an object-specific callback from the static version by calling this->someCallback (where this is the pointer stored in the userdata, of course).
Not directly.
The non-static function pointer (known as a member function pointer) has a hidden 'this' parameter so the types don't match. The static function has no 'this' pointer.
To get around this, you need to be able to pass in a user data item which is the 'this' pointer of the object you want to use as a callback. Then, specify a static member that is passed the user data, converts it to a pointer to the class object and calls the non-static member on it.
Looking at the code you've posted, it's hard to tell if there is a user data object, possibly the last-but=one parameter.
No, a non-static member would expect an object, and the caller (call-backer) does not have and will not provide one.
No. Non-static methods need an object to operate on. If you were to merely pass the method you would also need some way to tell the function which object to call the method on.
A non-static function has an implicit this parameter, and thus would have the wrong signature for the callback.
Sorry, no easy way to avoid the jump island.
if you put this line in your constructor (or in any instance method) then you should be able to do this.instanceMethod() to refer to the instance method.
EDIT
I just noticed you are using the user space IOKit API, not the kext side, which makes this post irrelevant.
Assuming you are working within the OS X kernel, you actually can do this.
You can use the OSMemberFunctionCast macro to convert a member function pointer to a plain C function pointer, do note that it should be called with the first argument pointing to an instance of the class, eg.
IOServiceMatchingCallback mycb = OSMemberFunctionCast(IOServiceMatchingCallback,
&myclassinstance, &MyClass::cb_method);
result = IOServiceAddMatchingNotification(
mNotifyPort,
kIOMatchedNotification,
IOServiceMatching( "IOFireWireLocalNode" ),
mycb,
&myclassinstance,
&enumerator);