I\'m using a 3rd party library that allows me to register callbacks for certain events. The register function looks something like this. It uses the Callback signature.
Due to the inflexible hardcoding of an actual function type for the callback you can't use any of the normal adapting or binding tricks to help you here. The third party library really wants you to pass in a non-member function and there isn't much you can do. You may want to consider why you're trying to pass it the address of a member function, and if your design or use of the library could change.
One option, if you only need to set a single callback, is to have a static or namespace private function that refers to a singleton instance pointer, and uses that to dispatch upon callback.
If you need multiple items, then possibly a template would wrap the hackiness (untested code here, just the idea).
template <int which_callback>
struct CallbackHolderHack
{
static int callback_func(std::string str) { dispatchee_->myCallback(str); }
static MyStruct* dispatchee_;
};
template <int which_callback>
MyStruct* CallbackHolderHack::dispatchee_(0);
And use it:
CallbackHolderHack<0>::dispatchee_ = new MyStruct;
registerCallback(&CallbackHolderHack<0>::callback_func);
Depends on how you are using it.... eg a Singlton would be much simplier
struct MyStruct {
static MyStruct& Create() {
static MyStruct m; return m;
}
static int StaticCallBack(std::string str) {
return Create().Callback(str)
}
private:
int CallBack(std::string str);
MyStruct();
};
Or if you want to have many of these objects you have several choices. You would need a way to route it before the callback is called.
class ICallBackInterface
{
public:
virtual void FireCallBack( std::string& str ) = 0;
};
std::set<ICallBackInterface*> CallBackMgr;
class MyStruct : public ICallBackInterface
{
public:
MyStruct()
{
CallBackMgr.insert( this );
}
~MyStruct()
{
CallBackMgr.erase( this );
}
virtual void FireCallBack( std::string& str )
{
std::cout << "MyStruct called\n";
}
};
void FireAllCallBack(std::string& str )
{
for ( std::set<ICallBackInterface*>::iterator iter = CallBackMgr.begin();
iter != CallBackMgr.end();
++iter)
{
(*iter)->FireCallBack( str );
}
}
This is another way to use polymorphism to achieve the same effect
Since you are using C++, why not make the callback a functor object? Then you can use std::mem_fun.
Edit: Seems std::mem_fun
has been deprecated in the latest C++11 standard. So std::function might be a better solution if you have a new compiler.
See this SO question for hints about using it.
Member functions are not convertible to the normal functions for its own good reasons. If your design allows, then make MyStruct::myCallback()
a static
member method and the code should work fine.
struct MyStruct {
...
static int myCallback(std::string str);
^^^^^^
};
You're trying to pass a member function pointer as a normal function pointer which won't work. Member functions have to have the this
pointer as one of the hidden parameters, which isn't the case for normal functions, so their types are incompatible.
You can:
static
)std::string
and use something like boost's bind
to bind the first two argumentsstd::function
(I think that's the name)