【问题标题】:OO Design: Multiple instances but Static CallbacksOO 设计:多实例但静态回调
【发布时间】:2014-05-08 13:17:30
【问题描述】:

我正在尝试将 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_lib_type 有一个客户提供数据的字段,您可以使用它。否则,恐怕你倒霉了。
  • c_lib_type 是什么?
  • 回调是否可以在任何时候突然发生,还是仅在您的应用程序执行涉及已知 CObj 实例的某些操作时发生?如果是后者,您可以求助于丑陋的解决方案,将static CObj* currentThis 放入 CObj 并在触发回调之前将其设置为正确的值。
  • @DieterLücking c_lib_type 是一种抽象数据类型,源自 C 库。
  • @dlf 回调可能随时发生。

标签: c++ c oop callback


【解决方案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++ 对象和静态成员函数对。 在调用时,您将用户数据转换为传递给注册的类对象。

没有上述内容,您将进退两难。您将调用对象存储在一个全局变量中并在回调函数中使用它,使回调绑定到单个对象,只有!。

【讨论】:

    【解决方案2】:

    您的编辑暗示了以下想法:

    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 所困扰。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多