Passing a pointer to member function
-
17-06-2021 - |
Question
There are a number of examples out there but yet I can't seem to figure out the solution to my problem. I have
class FooSource{
...
void StartGetFoos(void (*callback)(vector<IFoo*>*, IAsyncResult));
...
}
When StartGetFoos()
is called, a request it done to get Foos, saving the callback. when the request it complete (takes about 30 secs), the saved callback is called with results.
I cannot change the signature of this method.
and somewhere else I have a class
class FooUser {
...
void FooUser::MyCallback(vector<IFoo*>* foos, IAsyncResult result)
{
// marshall to UI thread and update UI
}
void init()
{
fooUser->StartGetFoos(??????);
// how do I pass my callback member function here?
}
}
Solution
There's nowhere on the signature void (*callback)(vector<IFoo*>*, IAsyncResult)
for you to receive a this
pointer, so you can't use a member function. Instead you'll have to use a static
member function:
class FooUser {
static void MyCallback(vector<IFoo*>* foos, IAsyncResult result)
{
// marshall to UI thread and update UI
}
void init()
{
fooUser->StartGetFoos(&FooUser::MyCallback);
}
};
The issue here is that you won't be able to access any instance data on FooUser
; this may or may not be a problem.
Depending on how well the API is designed, there may be a way to pass an instance pointer e.g. via IAsyncResult result
.
OTHER TIPS
If IAsyncResult is a data structure that get's passed in, and then back out again for the operation, you could extend it with your own information.
class MyAsyncResult : public IAsyncResult
{
public:
MyAsyncResult(FoorUser *sender) : sender(sender){}
FooUser *sender;
};
Then, as ecatmur says, you can specify a static member function for the callback, but you can also make a regular member function that gets called afterwords:
Static member functions have no access to the class members, but can be specified as callbacks where a normal C function would normally be required.
class FooUser
{
// static with no access to class members, but can be specified as a callback.
static void MyCallback(vector<IFoo*>* foos, IAsyncResult *result)
{
MyAsyncResult *res = (MyAsyncResult*)result;
res->sender->MyCallback(foos, result);
}
void MyCallback(vector<IFoo*>* foos, IAsyncResult *result)
{
// handle the actual callback here
}
void init()
{
IAsyncResult *res = new MyAsyncResult(this);
fooUser->StartGetFoos(&foos, res);
}
}