I need to wrap a C++ library with C. This C++ library defines callback functions. For example:
// from C++ library
typedef X CallbackFn(Y y); // X and Y are classes
class Z
{
public:
void addCallback( CallbackFn* fn ) { callbackFn = fn; }
private:
CallbackFn* callbackFn;
};
In the C wrapper I could define new C callbacks, which call the C++ callbacks. Something like this:
// in C wrapper
extern "C" {
typedef int CallbackFnC(int n, ... );
CallbackFnC *callbackFnC;
int addCallback(void* handle, CallbackFnC* fn) // handle is pointer to Z instance
{
callbackFnC = fn;
((Z*)handle)->addCallback(callbackFnCPP);
}
}
X callbackFnCPP(Y y)
{
int rtn = callbackFnC(y.n, ...);
return X(rtn);
}
where I assume I can map the relevant members of Y to the arguments of the C callback function and that I can sufficiently construct the return type X from the C return.
Is this going to work? There's no way around defining the new C callbacks?
The new C callback should be inside the extern "C"
and the defined instance of the C++ callback should be outside?
Yes, replacing the C++ callback with a C callback and a C++ wrapper function will work (with some caveats) and no, if the C++ callback insists on passing/returning classes or references (as opposed to primitive types supported also by C), then the wrapper method is the only possible solution.
The main caveat of using a wrapper function is that the wrapper function needs some way to find the correct C function to call. Using a global is an easy solution, but now you are limited to one callback for the entire program (regardless of the number of Z objects you have). More flexible solutions will depend on the design of the C++ callback and will range from easy (on registration, you can provide arbitrary user-data that will be provided to the callback) to very hard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With