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
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 );
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).
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.
No, a non-static member would expect an object, and the caller (call-backer) does not have and will not provide one.
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.
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.
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.
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);
Related
I have a base class which contains WNDPROC member, but some derived classes such as controls use SUBCLASSPROC instead, both of which are function pointers to window procedure, just different prototype.
I want to avoid having 2 members in all derived classes because only one will by used by all instances.
So my question is, can I reinterpret_cast from one function pointer to another and then cast back again? is it safe?
for example:
SUBCLASSPROC fnptr = /* some function */
WNDPROC data = reinterpret_cast<WNDPROC>(fnptr);
// is this pointer "original_pointer" valid now?
SUBCLASSPROC original_pointer = reinterpret_cast<SUBCLASSPROC>(data);
Basically in this example the data pointer is only used to store function pointer of different type.
btw. I know I could use templated member, but my design does not allow it, since data pointer is a member of yet another structure over which I have no control.
Edit How is this in any way related to the supposed post? They are both completely different errors, you guys should really stop trying to farm rep
So I've been searching around google and stackoverflow but I couldn't find one solution that would help my case.
I have a D3D9Device pointer and I want the EndScene address of that device, how would I approach so?
DWORD aEndScene = *(DWORD*)(&d3ddev->EndScene);
won't work with the following error
'&': illegal operation on bound member function expression
I think that's wrong because I'm actually trying to get the address of the d3ddev class
Member function pointers are not per object, they are per type. In your example, you could have multiple instances of a IDirect3DDevice9, all of which would have the same pointer value for their EndScene member function (assuming they aren't different concrete types - but this isn't likely).
The specific error you are getting is because you are attempting to get the address of a pointer-to-member function from an object, which isn't valid (eg. see '&' illegal operation on bound member function expression error).
It is possible to get the value of a member function using the type, instead of an object pointer. However, it's extremely ugly:
// Value is stored in 'end_scene':
HRESULT (IDirect3DDevice9::* end_scene)() = &IDirect3DDevice9::EndScene;
// Call the function, with the value of 'end_scene'.
(*d3ddev.*(end_scene))();
// Print the address of the pointer-to-member function:
printf("%p\n", end_scene);
I wouldn't suggest doing this here, because most functions in IDirect3DDevice9 don't have the same prototype. In fact, only BeginScene has the same prototype as EndScene, and it's hard to imagine a situation in which the call could be one or the other, since they need to be called in a specific order. You could make the case about using this for the functions that get/set vertex/pixel shader constants, as they have the same prototypes, but, it's just as easy to store some other external state to determine which function to call, and much more straightforward.
I have the class object Chat *p, and I'm looking to run the method Foo(int num) on it (usually running by p -> Foo(3) for example).
I've written this code :
std::thread F(&Chat::Foo, 4);
though, it does not compile to me, and I also see theres an error, since I was not able to put p -> Foo into it (instead of &Chat::Foo...)
How can I run this code correctly?
Thanks!
The answer from how object methods actually work. When you call p->foo(3) what the compiler translates it to, roughly speaking, is Chat::foo(p, 3). P is always passed as a hidden parameter in any call to a function. C++ doesn't show you this and you can't actually call Chat::foo(p, 3), this just isn't allowed, but it roughly how things work in reality.
The variable this that is available in any member function is just the address that is passed in as the hidden first parameter and any member variables that you access in the function reference the hidden first parameter. So... what you need to do in order to call any member function as the starting point to a thread, is pass the pointer to the object as it's first parameter. std::thread F(&Chat::Foo, p, 4); will, I believe, start the thread properly.
I have the following problem.
I got a class PluginLoader which oversees loading of plugins. It divides sub-stages of work to other classes like Plugin. Plugin calls functions of PluginLoader in its processing. Let's call that function AddData. Here, PluginLoader has to check if the data it receives is duplicate. For that, it uses a ConflictResolver class. Now, my problem is how to make an object of ConflictResolver available to PluginLoader. There are 3 ways I see out of this.
Use a ConflictResolverFactory class and create an object of ConflictResolver for PluginLoader.
Pass a constructed ConflictResolver* to the PluginLoader via its constructor or a member function SetConflictResolver and store it in a member variable and use it later. Both ways have drawbacks. If I pass it in the constructor, I will have to throw if the pointer is NULL. And I can't use exceptions as it is the custom here. If I pass it via SetConflictResolver, there is no way that I can guarantee that that function will be actually called by the user. Or I will have to check whether the member ConflictResolver* is NULL everywhere I use it.
Pass a ConflictResolver & to PluginLoaders Load method where all the work will be done. In turn, Plugins Load method has to accept a ConflictResolver & as well (though it has no use for it) and pass that back to AddData where PluginLoader will be able to use it.
Third method is safer compared to second. However, I have to pass around a reference even when it is not used.
If the first method cannot be used, what is the best way to do this?
Apologies for the wall :wq!
You could pass a ConflictResolver& to the PluginLoader constructor. You can now guarantee that the object is not null.
So, I'm using the FMOD api and it really is a C api.
Not that that's bad or anything. Its just it doesn't interface well with C++ code.
For example, using
FMOD_Channel_SetCallback( channel, callbackFunc ) ;
It wants a C-style function for callbackFunc, but I want to pass it a member function of a class.
I ended up using the Win32 trick for this, making the member function static. It then works as a callback into FMOD.
Now I have to hack apart my code to make some of the members static, just to account for FMOD's C-ness.
I wonder if its possible in FMOD or if there's a work around to link up the callback to a specific C++ object's instance member function (not a static function). It would be much smoother.
You cannot directly pass a member function. A member function has the implicit parameter this and C functions don't.
You'll need to create a trampoline (not sure the signature of the callback, so just doing something random here).
extern "C" int fmod_callback( ... args ...)
{
return object->member();
}
One issue is where does that object pointer come from. Hopefully, fmod gives you a generic context value that will be provided to you when your callback is made (you can then pass in the object pointer).
If not, you'll just need to make it a global to access it.
I guess it supposed to work like this:
You can assign some user data to channel by calling FMOD_Channel_SetUserData. This user data should be a pointer to your C++ object that handles events.
Then you should write C-style callback that extracts that object by calling FMOD_Channel_GetUserData and then calls your C++ instance method on that object.
There is a non-portable, and pretty hackish solution that has the advantage of at least being thread-safe, which the "trampoline" methods are not.
You can generate the actual function machine code on the fly. The basic idea is that you have a template for your call-back function that takes an object pointer and a member-function pointer and gives you a block of heap memory that you can pass to the library as a C call-back function, that will, when called, turn around and call the member function on that object.
It's messy, and you'll have to provide an implementation for any new platform (any time the calling convention changes), but it works, is thread-safe. (Of course you'll also have to watch out for DEP). The other thread-safe solution is to resort to thread-local storage (assuming that you know the call-back will happen on the same thread as the call you made).
See http://www.codeproject.com/KB/cpp/GenericThunks.aspx for an example of how you could go about generating thunks.
Using only a function pointer (and no additional separate object pointer) for a C callback is a broken design, in my humble opinion.
If the function were, instead, FMOD_Channel_SetCallback(channel, callbackFunc, callbackObj), then your static method just takes an instance of the object, then calls callbackObj->func() (which obviously can be non-static).
you need to use a trampoline and store the pointer to the object you want to get the member function called on in a global or static variable, i.e.
Object *x;
void callback_trampoline() { x->foobar(); }
...
FMOD_Channel_SetCallback(CHANNEL, callback_trampoline);