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?
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.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: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.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.
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 usestd::bind
to bind a non-static member function but I can't recall the syntax off the top of my head.This should work if your member function is static.
Make sure it's in global scope
Use
extern "C"
Use
__cdecl
, if needed:void (_cdecl *callback)