I actually have a code (which I can't change) needs a static function as "callback function".
When I change the function to static, I can't access "this" and my class members then. Also I can't pass "this" as parameter to function, again because I can't change the original SDK and definition files, so what can I do?
My code is in a class, one of class functions calls a function which needs a "static callback function" as parameter.
That "callback function" needs also to access "this" and other class members to process.
What can I do?
I'm using QT and VS 2012 as compiler.
Thanks
A static function is in common with a global function, u can't image that u can use "this" in a global function, and not to mention class members...
The only difference is a static function has a "namespace" as known as the calss name.
So, no matter what are you using or which compliler it is, you cannot use "this" or class members in a static function, it's just language features.
And you should modify your code as Mike says.
If you use modern versions of C++ (11 or older) you may use std::bind. Or use boost:bind.
Related
There is a C library (which I cannot change) that supports a callback function of the type
void (*callback)(void *appContext, int eventid)
I want to set a C++ function as the callback.
Specifically I have following questions?
Do I need to declare the callback function under "extern C" block?
Does a member function need to be static to be the callback function? Is it possible to use a non-static member function? If yes, how? And when is it recommended to use a non-static member function?
Does it matter if the function is a template function or not?
Does a non-class C style function have any advantages over a class member function?
I am trying these variants on a old VC++ compiler, which does not support the latest C++ standard. But the code needs to be platform independent and should work on most C++ compilers. I want to know what is recommended practice with callbacks?
Does callback function need to be declared under extern "C"?
NO. extern "C" is necessary only when you are calling a C++ function directly, without the use of function pointers, from C. If function pointers are used, extern "C" is not required.
Can I use non-static member functions as a callback?
NO. Non-static member functions of class A have an implicit first parameter corresponding to this pointer.
Can I use static member functions as a callback?
YES, as long as signature matches with that of the callback.
Does it matter if the function is a template function or not?
NO, template function can be used as callbacks as long as the signature of the instantiated template matches with the callback.
Assuming appContext is an opaque pointer that you pass to the function making the callback, you can get a callback to a member function of a specific object like this:
class myclass {
void do_something() {
// call function making the callback using _event_handler
// as the callback function and the "this" pointer as appContext
}
// make sure the raw callback uses the correct calling convention (cdecl, stdcall, etc.)
static void _handle_event(void* appContext, int eventid) {
// forward the event to the actual object
static_cast<myclass *>(appContext)->handle_event(eventid);
}
void handle_event(int eventid) {
// do object-specific event handling
}
};
Several answers mention extern "C" as a requirement. This is simply incorrect.
extern "C" is necessary only when you are calling a C function directly from C++. It's used to tell the C++ compiler "do not apply name-mangling when generating the symbol name for this function". You are passing a C++ function pointer to a C function. As long as the calling conventions match, it will work just fine. The function's name is never involved.
This should work if your member function is static.
It is not as simple as declaring the callback function under an extern "C" block. You need to figure out what calling convention the C library uses for its functions.
The terms I'm going to use are Microsoft specific, but the same rules should apply to other platforms too.
By default, the Visual C++ compiler makes C function __stdcall and C++ functions __cdecl. You cannot mix and match these calling conventions since each of these makes different assumptions about who cleans the stack. Here's a more detailed explanation.
Once you've matched the calling conventions, the easiest approach is to declare your C++ callback function as a namespace scope free standing function; or if it needs to be a member function, then a static member function. In both cases you should be able to bind a pointer to the instance of the class using std::bind. You might even be able to use std::bind to bind a non-static member function but I can't recall the syntax off the top of my head.
Make sure it's in global scope
Use extern "C"
Use __cdecl, if needed: void (_cdecl *callback)
Strictly speaking, you cannot. A C callback must be designated extern "C", which is not possible for member functions. Only freestanding functions can be used. You may forward calls from there to any C++ function, including static or non-static member functions.
Depending on the platform, you sometimes may be able to get away with skipping extern "C", but I wouldn't test my luck.
I know that we should declare a function as static in a class if its a utility function or if we have to use in a singleton class to access private static member.
But apart from that does a static function provide any sort of compiler optimization too since it doesn't pass the "this" pointer? Why not just use the utility function through an already instantiated object of class? Or is it just a best practice to make utility functions as statics?
Thanks in advance.
The "non-passing-this" optimization can probably be done by the compiler once you turn the optimizations on. As I see it, a static function has rather idiomatic uses:
Implementing modules. There is a bit of overlap here with namespaces, and I would rather use namespaces.
Factories: you can make the constructor protected/private and then have several static functions (with different, explicit names) creating instances.
For function pointers: static functions do not require the slightly more complicated syntax of pointer to member function. That can be a plus when interacting with libraries written for C.
To keep yourself from using this and have the compiler to enforce it. It makes sense sometimes. For example, if you have a commutative operation that takes two instances, a static function that takes the two instances would emphasize (in my opinion) that the operation is commutative. Of course in many cases you would rather overload an operator.
In general a static function will ease namespace and "friend" clutter by prefixing an otherwise ordinary function with the name of a class, presumably because both are tightly related.
Static exists to associate a method with a class, rather than either:
Associating it with an instance of that class (like writing a normal, non-static member function).
Keeping it in the global namespace or whatever namespace you would otherwise be in (like declaring a function just in the file, not in a class).
Static says that 'conceptually this is something tied to/associated with this class, but it does not depend on any instance of that class'.
In more formal terms: a static member function is the same as a function declared outside of a class in all ways other than that it is part of that class's namespace and in that it has access rights to that class's private/protected data members.
Going back to your question:
There is no optimization gain here.
Utility function has nothing to do with it. It's whether or not it makes sense to scope the function in the class itself (rather than an instance of it).
It does not 'pass the this pointer' because there is no instance to speak of. You can call a static member function without ever invoking that class's constructor.
I have one little question for you :), I understand that every method "secretly" gets "this" pointer of some class that they are inside but why that wont happen to "friend" functions ?
Is it because they are NOT methods of class?
Can anyone explain whole machinery, i am very interested in how "this" really works!
thanks in advance! :)
friend functions and classes are just used for access control checked by the compiler.
friend functions are just standard functions, so there won't be any differences regarding calling conventions.
friend functions are not member of any class, so no this pointer is passed (as done with static member functions)
Non-static member function of a class will get a hidden this pointer (depending on the ABI this is often the first argument), static member functions don't get the this pointer because they don't act on instance data.
How exactly the this pointer is passed to a member function heavily depends on the used ABI, which depends on the architecture and operating system. Either it will be pushed on the stack, or it will be passed through a well known register.
Please consider reading "Where is the 'this' pointer stored in computer memory?".
"Friendship" and "Membership" are two different things. A function can be a member function or not, and independantly be a friend function or not.
You can declare a member function to be a friend function of another class, i.e.
class B{
friend void A::func(B);
//stuff
};
Here, the member function func from class A is declared as friend and can access B's private, and it will have a this pointer, that points to the object of class A on which func has been called.
The this pointer is an implicit parameter of non-static member functions, which is described in section 9.3.2 of the C++ Standard. How it is passed to the function depends on your compiler/architecture, i.e. it is implementation defined (so you might want to read your favorite compiler's documentation to learn about how it manages this pointers).
There is a C library (which I cannot change) that supports a callback function of the type
void (*callback)(void *appContext, int eventid)
I want to set a C++ function as the callback.
Specifically I have following questions?
Do I need to declare the callback function under "extern C" block?
Does a member function need to be static to be the callback function? Is it possible to use a non-static member function? If yes, how? And when is it recommended to use a non-static member function?
Does it matter if the function is a template function or not?
Does a non-class C style function have any advantages over a class member function?
I am trying these variants on a old VC++ compiler, which does not support the latest C++ standard. But the code needs to be platform independent and should work on most C++ compilers. I want to know what is recommended practice with callbacks?
Does callback function need to be declared under extern "C"?
NO. extern "C" is necessary only when you are calling a C++ function directly, without the use of function pointers, from C. If function pointers are used, extern "C" is not required.
Can I use non-static member functions as a callback?
NO. Non-static member functions of class A have an implicit first parameter corresponding to this pointer.
Can I use static member functions as a callback?
YES, as long as signature matches with that of the callback.
Does it matter if the function is a template function or not?
NO, template function can be used as callbacks as long as the signature of the instantiated template matches with the callback.
Assuming appContext is an opaque pointer that you pass to the function making the callback, you can get a callback to a member function of a specific object like this:
class myclass {
void do_something() {
// call function making the callback using _event_handler
// as the callback function and the "this" pointer as appContext
}
// make sure the raw callback uses the correct calling convention (cdecl, stdcall, etc.)
static void _handle_event(void* appContext, int eventid) {
// forward the event to the actual object
static_cast<myclass *>(appContext)->handle_event(eventid);
}
void handle_event(int eventid) {
// do object-specific event handling
}
};
Several answers mention extern "C" as a requirement. This is simply incorrect.
extern "C" is necessary only when you are calling a C function directly from C++. It's used to tell the C++ compiler "do not apply name-mangling when generating the symbol name for this function". You are passing a C++ function pointer to a C function. As long as the calling conventions match, it will work just fine. The function's name is never involved.
This should work if your member function is static.
It is not as simple as declaring the callback function under an extern "C" block. You need to figure out what calling convention the C library uses for its functions.
The terms I'm going to use are Microsoft specific, but the same rules should apply to other platforms too.
By default, the Visual C++ compiler makes C function __stdcall and C++ functions __cdecl. You cannot mix and match these calling conventions since each of these makes different assumptions about who cleans the stack. Here's a more detailed explanation.
Once you've matched the calling conventions, the easiest approach is to declare your C++ callback function as a namespace scope free standing function; or if it needs to be a member function, then a static member function. In both cases you should be able to bind a pointer to the instance of the class using std::bind. You might even be able to use std::bind to bind a non-static member function but I can't recall the syntax off the top of my head.
Make sure it's in global scope
Use extern "C"
Use __cdecl, if needed: void (_cdecl *callback)
Strictly speaking, you cannot. A C callback must be designated extern "C", which is not possible for member functions. Only freestanding functions can be used. You may forward calls from there to any C++ function, including static or non-static member functions.
Depending on the platform, you sometimes may be able to get away with skipping extern "C", but I wouldn't test my luck.
Why is the static keyword necessary at all?
Why can't the compiler infer whether it's 'static' or not?
As follows:
Can I compile this function without access to non-static member data? Yes -> static funcion.
No -> non-static function.
Is there any reason this isn't inferred?
If you expect the compiler to decide on the spot whether it's static or not, how does that affect external source files linking against the header file that just defines the method signatures?
The propery of being static or non-static affects the function type. Non-static member functions have an implicit this parameter, while static ones don't, for one example.
In other words, there's a major qualitative difference between static and non-static member functions. The compiler cannot "infer" this. This is a matter of the author's intent.
If I want (and need) my function to be non-static, I make it non-static, even if it doesn't access any non-static members of the class. If the compiler suddently decides to make my non-static function static just because it doesn't access any non-static members of the class, in general case it will destroy the functionality of the code.
Yes the compiler could, but it has no knowledge of your intent. And the original designers probably thought that supplying your intent was important.
Having redundancy in like this in the language helps to insure that many programmer errors will end up being caught by the compiler.
Another reason: If the function is static, it can't be overridden in derived classes. No polymorphism.