0

I have a callback with this signature (I'm using Live555):

typedef void(RTSPClient::responseHandler)(RTSPClient*, ...); //... = other parameters

Then in my code I have created a subclass of RTSPClient following the library rules:

class MyRTSPClient: public RTSPClient { 
... 

//callback 

void continueAfterDESCRIBE(RTSPClient *client, ...); //same signature of typedef

...

};

Now comes the problem.

In my code I have to invoke the following method:

unsigned RTSPClient::sendDescribeCommand(responseHandler, ...); //response handler is the typedef

If I create an object:

MyRTSPClient *client = MyRTSPClient::createNew(...); //is library requirement such creation

how can I pass the function object to sendDescribeCommand as callback?

Of course if I declare continueAfterDESCRIBE as static member I haven't any problem, but I want an object because I have many threads and if I use a static callback called from them many problems of synchronization will be raised.

So I'm struggling (as a newbie in C++) how to find out the correct signature to pass an obj->method as a callback.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
Chris
  • 277
  • 4
  • 15

2 Answers2

0

You cannot use a non-static member function as a callback parameter that expects a regular function, because their signatures are incompatible:

  • A non-member or a static member function takes only the parameters in its signature
  • A non-static member function takes an additional "hidden" parameter for the object on which it is called.

The common workaround for this is possible only if the library that performs a callback lets you pass custom parameters with the callback registration. This is usually done with a void* pointer, which you pass to the library when you register the callback, and then the library passes it back to you when it calls back the callback function.

Here is how:

// This is the static function that you register for your callback
static void staticContinueAfterDESCRIBE(RTSPClient *client, ...) {
    static_cast<MyRTSPClient*>(client)-> continueAfterDESCRIBE(client, ...);
}

Now that the function is static, you have no problem registering it as a callback. Once the function gets the control, it casts client to your MyRTSPClient* class, and performs the non-static callback.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thank you Sir. In your opinion, if I made as your precious advice, does each thread that calls the static callback (as a wrapper if I well undestood) works on a separate "continueAfterDESCRIBE" avoiding me to syncronize them to the method? – Chris Nov 20 '14 at 17:29
  • @Chris Since the `client` is passed back to you by the library, the threading is controlled by the library as well: if each thread has its own `client`, then you do not need to synchronize. If multiple threads could share the same `client`, then you would need to synchronize. In any event, you would need to synchronize `continueAfterDESCRIBE`, not `staticContinueAfterDESCRIBE`, because the static wrapper never accesses any shared resources explicitly. – Sergey Kalinichenko Nov 20 '14 at 17:33
0

You want two pointers, one to an object and one to the member function:

void (RTSPClient::*mfptr) = &RTSPClient::continueAfterDESCRIBE;

and one to an object:

RTSPClient* p = new RTSPClient();

and then call it:

p->*mfptr(...);
Paul Evans
  • 27,315
  • 3
  • 37
  • 54