I use a third-party library that requires to have pointers to static functions passed as callback arguments. For now I have to do something like this:
static int MyCallback( ...)
{
// Callback code here...
}
int main( int argc, char* argv[])
{
ThirdPartyFunction( &MyCallback, ... );
}
What I would like to do is to replace the static callback function I have to provide by a member method of an instance of a C++ class. Something like this:
class MyClass
{
public:
int MyCallbackMethod( ... );
};
int main(int argc, char* argv[])
{
MyClass instanceOfMyClass;
ThirdPartyFunction( &(????), ... );
}
My problem is that it doesn't compile when I pass &instanceOfMyClass::MyCallbackMethod
to ThirdPartyFunction()
. When starting a thread (say, a std::thread) one passes (&MyClass::MyCallbackMethod, this)
but in this case, the ThirdPartyFunction
(that seems to be written in C rather than in C++ ?) doesn't allow me to pass a function pointer and an object owning the method.
On the other hand, if I declare static int MyCallbackMethod
in MyClass
, of course it works but I don't have an instance and it is not what I want.
My question is simple: is it possible to pass something like (&MyClass::MyCallbackMethod, this)
(instance method) in place of &MyClass::MyCallbackMethod
(static method)? I'm using C++11.
Thanks in advance for your help!
EDIT 1
I use libmicrohttpd (see microhttpd.h)
Function "ThirdPartyFunction
":
_MHD_EXTERN struct MHD_Daemon *
MHD_start_daemon_va (unsigned int flags,
uint16_t port,
MHD_AcceptPolicyCallback apc, void *apc_cls,
MHD_AccessHandlerCallback dh, void *dh_cls,
va_list ap);
and MHD_AcessHandlerCallback
, for example, is declared as:
typedef int
(*MHD_AccessHandlerCallback) (void *cls,
struct MHD_Connection *connection,
const char *url,
const char *method,
const char *version,
const char *upload_data,
size_t *upload_data_size,
void **con_cls);
So I have to use a function that has this signature. I would like to use the same signature but on an instance method rather than a static function.
You cannot pass a pointer to member function in place of a pointer to a non-member or a static member function, because member functions require an object on which they are invoked. A pointer to that object becomes the implicit this
parameter of your member function.
If you need to dispatch a call to a member function, there needs to be a way to find the object on which the function is being invoked. There are two general approaches here:
In both cases you register a static or a non-member function as a callback function to your third-party API.
Here is an example of the first approach:
struct MyClass {
int MyCallbackMethod( ... );
};
static MyClass *instancePointer;
static int MyStaticCallback( ...) {
instancePointer->MyCallbackMethod(...);
}
int main(int argc, char* argv[]) {
MyClass instanceOfMyClass;
// Point instancePointer to instanceOfMyClass for the static callbacl
instancePointer = &instanceOfMyClass;
// Register static callback
ThirdPartyFunction( &MyStaticCallback, ... );
}
The second approach depends on the API. Assuming that your callback receives a void*
that you can pass to ThirdPartyFunction
, the implementation goes like this:
struct MyClass {
int MyCallbackMethod( ... );
};
static int MyStaticCallback(void* userData) {
MyClass *instancePointer = (MyClass*)userData;
instancePointer->MyCallbackMethod();
}
int main(int argc, char* argv[]) {
MyClass instanceOfMyClass;
ThirdPartyFunction( &MyStaticCallback, (void*)(&instanceOfMyClass));
}
In your situation it looks like the cls
pointer is what's being passed back to your callback, and apc_cls
/ dh_cls
is what you pass to third-party function for registration.