7

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

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

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

谢谢

4

8 回答 8

7

IOServiceMatchingCallback的原型与非静态类方法不兼容(从技术上讲,与静态类方法也不兼容),因此您将无法使用它。

但幸运的是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 并且您有一个 this 指针):

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             serviceMatchingCallback, 
             this,
             &enumerator );
于 2010-01-20T00:44:28.033 回答
4

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

于 2010-01-19T22:46:28.923 回答
2

不是直接的。

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

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

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

于 2010-01-19T22:48:42.013 回答
0

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

于 2010-01-19T22:44:36.260 回答
0

不,非静态成员需要一个对象,而调用者(call-backer)没有也不会提供一个。

于 2010-01-19T22:44:35.937 回答
0

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

抱歉,没有简单的方法可以避开跳跃岛。

于 2010-01-19T22:45:08.023 回答
0

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

于 2010-01-19T22:45:26.883 回答
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);
于 2010-01-20T01:00:18.823 回答