1

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?
    }
}
Professor Chaos
  • 8,850
  • 8
  • 38
  • 54

2 Answers2

3

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.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • Can you expand on how to use a static member function in this case? I was looking at [this post](http://stackoverflow.com/questions/400257/how-can-i-pass-a-class-member-function-as-a-callback) earlier and looked promising but I couldn't transform things for my situation. Thanks for the help. – Professor Chaos Jun 25 '12 at 21:32
  • 1
    @ProfessorChaos, use the static member function to call another non-static member function. To do that the static function needs to get an object pointer from somewhere, possibly a static member pointer variable if you never have more than one callback outstanding. – Mark Ransom Jun 25 '12 at 21:54
2

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);
    }
}
CuriousGeorge
  • 7,120
  • 6
  • 42
  • 74