OO设计:多个实例但是静态回调



我试图在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);
}

一个有用的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++对象和静态成员函数对。在调用时,将用户数据强制转换为传递给注册的类对象。

没有以上,你会陷入两难境地。您将把调用对象存储在一个全局变量中,并在回调函数中使用它,使回调仅限于单个对象。

你的编辑建议如下:

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();
}

这当然是一个hack,但我认为你在你所受的约束下被困在了hack。

最新更新