I have an old .dll with plain C interface which takes callbacks to invoke when some work is done. The callback it takes is of type void (f*)(char* arg)
.
I'm looking for a trick to pass a C++ function object there so that the callback is invoked with "this" pointer stored somewhere, something like bind, but simple bind doesn't work
To illustrate this: C interface:
typedef void (f*)(char* param) Callback;
void registerCallback(Callback c);
Usage in C++:
class A
{
void func1()
{
registerCallback(std::bind(&A::func2, _1, this)); // obviously doens't work
}
void func2(char* param)
{ ... }
};
The only way that to make this work with an instance of a class and a member function of the class, that I am aware of, is:
class A
{
void func1();
void func2(char* param)
{ ... }
};
// Global pointer
A* aPtr = NULL;
// Non-member function.
// extern "C" is probably needed if the older DLL is expecting
// an unmangled C function pointer.
extern "C" void globalFunc2(char* param)
{
if ( aPtr == NULL )
{
// Deal with error
}
else
{
aPtr->func2(param);
}
}
void A::func1()
{
aPtr = this;
registerCallback(globalFunc2);
}
The way I see it, the core of the problem is letting the caller of the callback function (the entity registerCallback
is registering with) know which A
object's func2
to call.
As far as I can understand from your problem, you basically have a bunch of A
objects and you only want a number of these A
objects to execute their respective func2
s when the callback event occurs. However, the caller of the callback function does not know who to call when the callback event occurs. Since you mentioned that it's an old .dll, I assume we cannot just go in and change how registerCallback
works, but we need to store the A
objects that are registered for callback.
Therefore,
class Informer {
public:
static void InformAllMembers(char* param) {
for(auto& a : m_Members) { //Inform all As registered with me
a->func2(param);
}
}
static void Register(A* a) {
m_Members.push_back(a);
}
private:
static std::vector<A*> m_Members;
};
std::vector<A*> Informer::m_Members;
...
registerCallback(Informer::InformAllMembers);
A a;
Informer::Register(&a);
NOTE: You will have to handle cases where some of the registered A
objects are destroyed and unregister them from the Informer
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With