如何通过回调传递非静态会员函数?

发布于 2025-01-30 19:32:41 字数 525 浏览 3 评论 0 原文

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

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

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

谢谢

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


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

if i declare serviceMatchinCallback as static then it works, but i do not want it to be static. Is there a way to pass it a non-static callback function?

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

静若繁花 2025-02-06 19:32:41

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 from a member功能,您有一个指针):

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

The prototype for IOServiceMatchingCallback is not compatible with a non-static class method (and technically is not compatible with a static class method either), so you are not going to be able to use that.

But luckily IOServiceAddMatchingNotification supports a context pointer (or as they call it, a refCon) which will allow you to create a thunk that does not rely on global data.

You need to define a callback with compatible linkage (i.e. extern "C"). This function will cast your refCon to your object pointer and then forward the call to your instance method:

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

Then, when you call IOServiceAddMatchingNotification, make sure to pass a pointer to your object for refCon (here I'm assuming you call IOServiceAddMatchingNotification from a member function and you have a this pointer):

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             serviceMatchingCallback, 
             this,
             &enumerator );
楠木可依 2025-02-06 19:32:41

您可以保持其静态,但是使用UserData除了您想要的任何其他UserData之外(例如,通过将它们打包成一个结构),然后调用特定于对象的回调,但使用UserData存储指针通过调用 this-&gt; somecallback (其中当然是存储在用户达塔中的指针),该静态版本。

You could keep it static, but use the userdata to store the this pointer in addition to whatever other userdata you want (by packing them into a structure, for example) and then call an object-specific callback from the static version by calling this->someCallback (where this is the pointer stored in the userdata, of course).

雾里花 2025-02-06 19:32:41

不是直接。

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

To get around this, you need to be able to pass in a user data item which is the 'this' pointer of the object you want to use as a callback. Then, specify a static member that is passed the user data, converts it to a pointer to the class object and calls the non-static member on it.

Looking at the code you've posted, it's hard to tell if there is a user data object, possibly the last-but=one parameter.

Not directly.

The non-static function pointer (known as a member function pointer) has a hidden 'this' parameter so the types don't match. The static function has no 'this' pointer.

To get around this, you need to be able to pass in a user data item which is the 'this' pointer of the object you want to use as a callback. Then, specify a static member that is passed the user data, converts it to a pointer to the class object and calls the non-static member on it.

Looking at the code you've posted, it's hard to tell if there is a user data object, possibly the last-but=one parameter.

情定在深秋 2025-02-06 19:32:41

不,非静态成员会期望一个对象,而呼叫者(呼叫者)没有,也不会提供一个。

No, a non-static member would expect an object, and the caller (call-backer) does not have and will not provide one.

笑脸一如从前 2025-02-06 19:32:41

否。非静态方法需要一个对象才能操作。如果您仅通过该方法,您还需要某种方法来告诉该函数哪个对象要调用该方法。

No. Non-static methods need an object to operate on. If you were to merely pass the method you would also need some way to tell the function which object to call the method on.

玩世 2025-02-06 19:32:41

非代码>静态函数具有隐式 this 参数,因此在回调中会有错误的签名。

抱歉,没有简单的方法来避免跳跃岛。

A non-static function has an implicit this parameter, and thus would have the wrong signature for the callback.

Sorry, no easy way to avoid the jump island.

旧伤慢歌 2025-02-06 19:32:41

如果将此行放入构造函数(或在任何实例方法中),则应该可以执行此操作。

if you put this line in your constructor (or in any instance method) then you should be able to do this.instanceMethod() to refer to the instance method.

半岛未凉 2025-02-06 19:32:41

编辑
我只是注意到您正在使用用户空间IOKIT API,而不是Kext side,这使该帖子无关紧要。


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

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

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

EDIT
I just noticed you are using the user space IOKit API, not the kext side, which makes this post irrelevant.


Assuming you are working within the OS X kernel, you actually can do this.
You can use the OSMemberFunctionCast macro to convert a member function pointer to a plain C function pointer, do note that it should be called with the first argument pointing to an instance of the class, eg.

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

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             mycb,
             &myclassinstance,
             &enumerator);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文