2014-11-20 103 views
0

我有一个回调与此签名(我使用LIVE555):回调成员函数

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

然后在我的代码我已经创建以下图书馆的规则RTSPClient的子类:

class MyRTSPClient: public RTSPClient { 
... 

//callback 

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

... 

}; 

现在出现这个问题。

在我的代码必须调用下面的方法:如果我创建一个对象

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

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

我怎么能传递函数对象sendDescribeCommand回调?

当然,如果我声明continueAfterDESCRIBE为静态成员,我没有任何问题,但我想要一个对象,因为我有很多线程,如果我使用从它们调用的静态回调,将会引发许多同步问题。

所以我很挣扎(作为C++中的新手)如何找出正确的签名来传递obj->method作为回调。

回答

0

不能使用非静态成员函数作为期望一个普通函数回调参数,因为他们的签名是不兼容的:

  • 非成员或静态成员函数采用仅在参数的签名
  • 非静态成员函数为调用它的对象提供额外的“隐藏”参数。

只有在执行回调的库允许您使用回调注册传递自定义参数时,此常见解决方法才有可能。这通常是通过指针void*来完成的,当你注册回调函数时,你将它传递给函数库,然后函数库在回调回调函数时将它传回给你。

方法如下:

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

现在的功能是静态的,你有没有问题,注册为回调。一旦函数获得控制权,它会将client投射到您的MyRTSPClient*类,并执行非静态回调。

+0

谢谢先生。在你看来,如果我作为你的宝贵意见,那么每个调用静态回调的线程(如果我很好undestood,作为一个包装)会在单独的“continueAfterDESCRIBE”上工作,从而避免我将它们同步到方法中? – Chris 2014-11-20 17:29:15

+0

@Chris由于'client'由库传回给你,所以线程也由库控制:如果每个线程都有自己的'client',那么你就不需要同步。如果多个线程可以共享同一个“客户端”,那么你需要同步。无论如何,您需要同步'continueAfterDESCRIBE',而不是'staticContinueAfterDESCRIBE',因为静态包装器从不显式访问任何共享资源。 – dasblinkenlight 2014-11-20 17:33:14

0

你想两个指针,一个物体和一个成员函数:

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

和一个对象:

RTSPClient* p = new RTSPClient(); 

然后调用它:

p->*mfptr(...);