OO设计:多实例但静态回调 我试图在C++中包装C库。库定义了一些回调函数,例如void(*callback)(void*),显然,在我的OO类中,这些回调函数必须是静态的

OO设计:多实例但静态回调 我试图在C++中包装C库。库定义了一些回调函数,例如void(*callback)(void*),显然,在我的OO类中,这些回调函数必须是静态的,c++,c,oop,callback,C++,C,Oop,Callback,我的问题是从回调函数中找到正确的类实例。在创建对象时,回调参数未知 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,

我的问题是从回调函数中找到正确的类实例。在创建对象时,回调参数未知

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函数(void*user\u data)
的签名,或者带有附加参数
R函数(A0 A0,A1 A1,…AN,void*user\u data)
。C库应该提供一个类似register\u函数(函数类型,void*用户数据)的函数

这样,您可以通过调用ReistStyFalm(Ac::StasyPixMeMySuffic函数)登记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();
}
模板
类CObjFactory
{
私人:
静态标准:弱ptr weakObj;
静态void CallbackFuncWrapper(void*arg)
{
auto strongObj=weakObj.lock();
如果(strongObj==nullptr)
返回;
strong对象->调用函数(arg);
}
公众:
静态std::shared_ptr Create()
{
自动strongObj=std::使_共享(CallbackFuncWrapper);
weakObj=strongObj;
返回strongObj;
}    
};
模板
标准::弱ptr CObjFactory::weakObj;
void main()
{
std::shared_ptr o1=CObjFactory::Create();
std::shared_ptr o2=CObjFactory::Create();
}

这当然是一种黑客行为,但我认为,考虑到您所受的限制,您会遇到黑客行为。

如果
c_lib_type
有一个用于客户端提供数据的字段,您可以使用该字段。否则,恐怕你就不走运了。什么是
c_lib_type
?回调可以在任何时候突然发生,还是只在应用程序执行某些涉及已知CObj实例的操作时发生?如果是后者,您可以求助于丑陋的解决方案,将
静态CObj*currentThis
放入CObj中,并在触发回调之前将其设置为正确的值。@DieterLücking c_lib_类型是一种抽象数据类型,源自c库。@dlf回调可能随时发生。