我需要用C包装一个C ++库。这个C ++库定义了回调函数。例如:
// 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;
};
在C包装器中,我可以定义新的C回调,它调用C ++回调。像这样:
// 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);
}
我假设我可以将Y的相关成员映射到C回调函数的参数,并且我可以从C返回中充分构造返回类型X.
这会起作用吗?有没有办法定义新的C回调?
新的C回调应该在extern "C"
内,并且定义的C ++回调实例应该在外面?
答案 0 :(得分:2)
是的,用C回调和C ++包装器函数替换C ++回调将起作用(有一些警告),如果C ++回调坚持传递/返回类或引用(与C也支持的基本类型相反) ),然后包装方法是唯一可能的解决方案。
使用包装函数的主要注意事项是包装器函数需要某种方法来找到要调用的正确C函数。使用全局是一个简单的解决方案,但现在您只能对整个程序进行一次回调(无论您拥有多少个Z对象)。更灵活的解决方案将取决于C ++回调的设计,范围从简单(在注册时,您可以提供将提供给回调的任意用户数据)到非常困难。