我试图用C ++包装C库。该库定义了一些回调函数,例如void (*callback)(void*)
,它在我的OO类中必须是静态的。显然。
我的问题是在回调函数中找到类的正确实例。在创建对象时不知道回调参数。
class CObj
{
public:
CObj()
{
c_lib_start(CObj::CallbackFunc);
}
static void CallbackFunc(void* arg)
{
c_lib_type* data = (c_lib_type*)arg;
// ... handle data callback
}
}
int main(int argc, char* argv[])
{
CObj obj1;
CObj obj2; // will call the same callback function as obj1! can this be avoided?
}
编辑:
经过一番思考,我最好的解决方案草案:
class CObj
{
public:
CObj(void (*pFuncPtr)(void*))
{
c_lib_start(pFuncPtr);
}
void CallbackFunc(void* arg)
{
c_lib_type* data = (c_lib_type*)arg;
// ... handle data callback
}
}
// globals. templated?
CObj* g_obj1 = NULL;
void FuncPtr1(void* arg) { g_obj1->CallbackFunc(arg); }
CObj* g_obj2 = NULL;
void FuncPtr2(void* arg) { g_obj2->CallbackFunc(arg); }
int main(int argc, char* argv[])
{
g_obj1 = new CObj(FuncPtr1);
g_obj2 = new CObj(FuncPtr2);
}
答案 0 :(得分:1)
有用的C回调函数具有R function(void* user_data)
或其他参数R function(A0 a0, A1 a1, ... AN an, void* user_data)
的签名。 C库应该提供类似register_function(function_type,void * user_data)的函数。
有了这个,你可以通过调用register_function(& Class :: static_member_function,this)来注册一对C ++对象和一个静态成员函数。 在调用时,您将用户数据转换为传递给注册的类对象。
如果没有上述,你就会陷入两难境地。您将调用对象存储在一个全局变量中,并在回调函数中使用它,使回调仅限于一个对象!
答案 1 :(得分:0)
您的修改提出了以下想法:
template<size_t SerialNumber>
class CObjFactory
{
private:
static std::weak_ptr<CObj> weakObj;
static void CallbackFuncWrapper(void* arg)
{
auto strongObj = weakObj.lock();
if(strongObj == nullptr)
return;
strongObj->CallbackFunc(arg);
}
public:
static std::shared_ptr<CObj> Create()
{
auto strongObj = std::make_shared<CObj>(CallbackFuncWrapper);
weakObj = strongObj;
return strongObj;
}
};
template<size_t SerialNumber>
std::weak_ptr<CObj> CObjFactory<SerialNumber>::weakObj;
void main()
{
std::shared_ptr<CObj> o1 = CObjFactory<0>::Create();
std::shared_ptr<CObj> o2 = CObjFactory<1>::Create();
}
这肯定是一个黑客攻击,但我认为考虑到你所受到的限制,你会陷入黑客攻击。