【问题标题】:Callback to a member function回调成员函数
【发布时间】:2014-11-20 17:01:08
【问题描述】:

我有一个带有此签名的回调(我正在使用 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 作为回调传递。

【问题讨论】:

    标签: c++ callback live555


    【解决方案1】:

    您不能将非静态成员函数用作需要常规函数的回调参数,因为它们的签名不兼容:

    • 非成员或静态成员函数只接受其签名中的参数
    • 非静态成员函数为调用它的对象附加一个“隐藏”参数。

    仅当执行回调的库允许您通过回调注册传递自定义参数时,才能使用常见的解决方法。这通常使用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* 类,并执行非静态回调。

    【讨论】:

    • 谢谢先生。在您看来,如果我按照您的宝贵建议提出建议,是否每个调用静态回调的线程(如果我没有理解,则作为包装器)在单独的“continueAfterDESCRIBE”上工作,避免我将它们同步到方法?
    • @Chris 由于库将client 传回给您,因此线程也由库控制:如果每个线程都有自己的client,那么您不需要同步。如果多个线程可以共享同一个client,那么您将需要同步。在任何情况下,您都需要同步 continueAfterDESCRIBE,而不是 staticContinueAfterDESCRIBE,因为静态包装器从不显式访问任何共享资源。
    【解决方案2】:

    你需要两个指针,一个指向对象,一个指向成员函数:

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

    一个对象:

    RTSPClient* p = new RTSPClient();
    

    然后调用它:

    p->*mfptr(...);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多