Reputation: 7360
Consider a library function that takes a callback function (pointer) as argument. If a regular function pointer is used, the function can be used with regular C and C++ functions, but no class methods can be used for that:
typedef void(*CALLBACK_T)(int);
void testCallback(CALLBACK_T cb){
cb(5);
}
void intOut(int i){
std::cout << i << std::endl;
}
class Test{
public:
void intOut2(int i){
std::cout << "Test: " << i << std::endl;
}
};
void test(void){
testCallback(&intOut);
Test t;
testCallback(&t.intOut2); //won't work
}
I could use std::function
to encapsulate class members, but this would break C compatibility.
The only option I can think of is to create an additional context pointer to the callback handler:
typedef void(*CALLBACK2_T)(int, void*);
void testCallback2(CALLBACK2_T cb, void* context){
cb(5, context);
}
but this would require to keep track of the context information as well (the callback isn't directly invoked within the library function).
Do you have a better idea how a callback can be used with C functions and C++ class members at the same time?
Upvotes: 0
Views: 193
Reputation: 612804
You have very little room to manoeuvre here. Overwhelmingly the most commonly used approach is an extra context pointer.
One plausible alternative is to create a thunk at runtime. That is you allocate some memory and mark it as executable. The memory then contains the instructions needed to call the member function. The subject of the call, the object instance, is located at a fixed offset relative to the thunk. This is pretty dirty work, and not exactly portable. I do not recommend it.
Upvotes: 1
Reputation: 9
The C equivalent to Test::intOut2() is :
intOut2(Test *this, int i)
So &t.intOut2 doesn't have the right type to be a CALLBACK_T.
It should work by specifying intOut2 as static :
class Test{
public:
static void intOut2(int i){
std::cout << "Test: " << i << std::endl;
}
};
Upvotes: 0
Reputation: 513
Imho there is no alternative.
If you do not want to keep track of the context in your library, there is no way to get the 'this' pointer to the callback function. You are forcing the consumer of your library to go for a global variable, which is very limiting.
Upvotes: 1