io_iterator_t enumerator;
kern_return_t result;
result = IOServiceAddMatchingNotification(
mNotifyPort,
kIOMatchedNotification,
IOServiceMatching( "IOFireWireLocalNode" ),
serviceMatchingCallback,
(void *)0x1234,
& enumerator );
serviceMatchingCallback((void *)0x1234, enumerator);
如果我将serviceMatchinCallback声明为静态然后它可以工作,但我不希望它是静态的。有没有办法将它传递给非静态回调函数?
谢谢
答案 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);