如何将非静态成员函数作为回调传递?

时间:2010-01-19 22:39:39

标签: c++ function callback member non-static

 
io_iterator_t enumerator;
kern_return_t   result;
result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             serviceMatchingCallback, 
             (void *)0x1234,
             & enumerator );

serviceMatchingCallback((void *)0x1234, enumerator);

如果我将serviceMatchinCallback声明为静态然后它可以工作,但我不希望它是静态的。有没有办法将它传递给非静态回调函数?

谢谢

8 个答案:

答案 0 :(得分:7)

IOServiceMatchingCallback的原型与非静态类方法不兼容(技术上是not compatible with a static class method either),因此您无法使用它。

但幸运的是IOServiceAddMatchingNotification支持一个上下文指针(或者他们称之为refCon),它允许你创建一个不依赖于全局数据的thunk。

您需要定义具有兼容链接的回调(即extern“C”)。此函数将refCon转换为您的对象指针,然后将调用转发给您的实例方法:

extern "C"
void io_callback(void *refcon, io_iterator_t iterator)
{
    myclass *c = static_cast<myclass *>(refcon);
    c->real_callback(iterator);
}

然后,当你调用IOServiceAddMatchingNotification时,请确保将指针传递给你的refCon对象(这里我假设你从一个成员函数调用IOServiceAddMatchingNotification并且你有一个这个指针):

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             serviceMatchingCallback, 
             this,
             &enumerator );

答案 1 :(得分:4)

你可以保持静态,但是除了你想要的任何其他用户数据之外,还可以使用userdata来存储this指针(例如,通过将它们打包到结构中),然后从中调用特定于对象的回调。静态版本通过调用this->someCallback(其中this是存储在userdata中的指针,当然)。

答案 2 :(得分:2)

不直接。

非静态函数指针(称为成员函数指针)具有隐藏的“this”参数,因此类型不匹配。静态函数没有'this'指针。

要解决此问题,您需要能够传入用户数据项,该用户数据项是要用作回调的对象的“this”指针。然后,指定传递用户数据的静态成员,将其转换为指向类对象的指针,并在其上调用非静态成员。

查看您发布的代码,很难判断是否存在用户数据对象,可能是last-but = one参数。

答案 3 :(得分:0)

没有。非静态方法需要一个对象来操作。如果你只是传递方法,你还需要一些方法来告诉函数哪个对象调用该方法。

答案 4 :(得分:0)

不,非静态成员会期望一个对象,并且调用者(回调者)没有,也不会提供一个。

答案 5 :(得分:0)

static函数具有隐式this参数,因此回调的签名错误。

对不起,没有简单的方法来避免跳岛。

答案 6 :(得分:0)

如果你将这一行放在构造函数中(或者在任何实例方法中),那么你应该能够执行this.instanceMethod()来引用实例方法。

答案 7 :(得分:0)

修改 我刚刚注意到你使用的是用户空间IOKit API,而不是kext端,这使得这篇文章无关紧要。


假设您在OS X内核中工作,实际上您可以这样做。 您可以使用OSMemberFunctionCast宏将成员函数指针转换为普通C函数指针,请注意应该使用指向类实例的第一个参数调用它,例如。

IOServiceMatchingCallback mycb = OSMemberFunctionCast(IOServiceMatchingCallback,
    &myclassinstance, &MyClass::cb_method);

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             mycb,
             &myclassinstance,
             &enumerator);