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

时间:2014-05-08 13:17:30

标签: c++ c oop callback

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

2 个答案:

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

这肯定是一个黑客攻击,但我认为考虑到你所受到的限制,你会陷入黑客攻击。