How to pass non-stationary member function as callback?

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

+6
c ++ function callback member non-static
source share
8 answers

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

+4
source share

The IOServiceMatchingCallback prototype is incompatible with the non-static class method (and technically it is not compatible with the static class method or ), so you cannot use it.

But, fortunately, IOServiceAddMatchingNotification maintains a context pointer (or, as they call it, refCon), which allows you to create a thunk that does not depend on global data.

You need to define a callback with a compatible connection (that is, extern "C"). This function will pass your refCon to your object pointer, and then redirect 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, be sure to pass a pointer to your object for refCon (here I assume that you are calling IOServiceAddMatchingNotification from a member function, and you have this pointer):

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

Not directly.

A pointer to a non-static function (known as a pointer to a member function) has a hidden parameter 'this', so the types do not match. A static function does not have a 'this' pointer.

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

Looking at the code you posted, it's hard to determine if there is a custom data object, perhaps the last but one parameter.

+2
source share

No, the non-static member will wait for the object, and the caller (call-backer) does not and will not provide it.

0
source share

Not. For non-static methods, an object is needed to work. If you just passed a method, you would also need a way to tell the function for which the object calls the method.

0
source share

A non- static function has an implicit this parameter and therefore has an incorrect signature for the callback.

Sorry, there is no easy way to avoid the island of jumping.

0
source share

if you put this line in your constructor (or in some instance method), you should be able to do this.instanceMethod () to access the instance method.

0
source share

EDIT I just noticed that you are using the IOKit API user interface and not the kext side, which makes this post inappropriate.


Assuming you are running the OS X kernel, you really can do it. You can use the OSMemberFunctionCast macro to convert a member function pointer to a simple C function pointer; note that it must be called using the first argument pointing to an instance of the class, for example.

 IOServiceMatchingCallback mycb = OSMemberFunctionCast(IOServiceMatchingCallback, &myclassinstance, &MyClass::cb_method); result = IOServiceAddMatchingNotification( mNotifyPort, kIOMatchedNotification, IOServiceMatching( "IOFireWireLocalNode" ), mycb, &myclassinstance, &enumerator); 
0
source share

All Articles