Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use std::bind to convert a pointer to member function into a pointer to function?

I want to pass a member function as a call-back. The call back is a basic function pointer.

So I have something like:

h file:

void (*pRequestFunc) (int someint) = 0;
void RegisterRequestCallBack(void (*requestFunc) (int someint))
{
    pRequestFunc = requestFunc;
}

class A
{
    void callBack(int someint);
}

Cpp File:

RegisterRequestCallBack(&A::callBack); // This does not work.

Note I have tried to extract this example from my larger example and cut out all the other stuff - so it might not be perfect.

The problem, as far as I understand, is that member function pointers really (under the hood) have an extra parameter (and instance - i.e. this) and are not compatible with normal function pointers.

the RegisterRequestCallBack() is in reality not my code - and so I can't change that.

So I read that boost::bind can do what I need - and I am hoping c++11 std::bind can do the same - but I could not figure out how to use it to effectively get a standard function pointer from a member function pointer...

I was going for something like:

std::bind(&A::callBack) ... that is about as far as I got, my understanding of the examples online is poor :(

like image 912
code_fodder Avatar asked Oct 20 '25 20:10

code_fodder


1 Answers

NathanOliver's comment is correct, and your suspicion is mostly correct. Exactly how pointers to member functions work is not specified, but including this as a hidden argument mostly works. You just need a bit of extra work for inheritance and pointers to virtual functions (yes, you can take their address too).

Now, often callbacks include a void* parameter under your control, which you can use to pass a A*. In those cases, you can write a wrapper (static) function that casts the void* back to A* and does the actual call to &A::callback.

That's not the case here. Registration takes a single function, without data. To get this to work in real-life situations, you have to resort to drastic solutions - not portable C++. One such method is to dynamically generate assembly (!). You create - at runtime - the compiled equivalent of

void __trampoline_0x018810000 (int i)
{
   A* __this = reinterpret_cast<A*>(0x018810000);
   __this->callback(i);
}

As you can see, you have to generate one trampoline for every A* value, and managing lifetimes of these is a major pain.

like image 139
MSalters Avatar answered Oct 23 '25 11:10

MSalters