使用需要函数指针的C库时的C++习惯用法?

Pla*_*ove 3 c++

我在C++应用程序中使用C库.C SDK具有将回调函数指针作为参数的函数.这些功能的签名通常如下:

typedef int (* Func) (type1 c, type2 d);
Run Code Online (Sandbox Code Playgroud)

我的代码是用C++中的类构建的.但是,我不能将任何成员函数作为回调传递给此函数,因为它不接受int (MyClass::*)(type1 c, type2 d)并且只接受int (*)(type1 c, type2 d).

我通过static在各个类中定义所有回调,然后将它们传递给C库然后工作来解决这个问题.

我还是C++的新手,所以我不确定这是否是正确的解决方案?代码有效,但我很想知道我做错了.

Rei*_*ica 6

在大多数平台上,您的代码可能会遇到,您的解决方案很好.但是,严格地说,可以有一个C调用约定和C++调用约定不同的平台.在这个平台上,你的代码不起作用.

100%正确的解决方案(与您使用的99.9%正确的解决方案相对)是使用C语言链接定义一个函数作为回调.如果您需要此函数来获得对您的类的成员访问权限,则可以static在您的类中调用成员函数:

class MyClass
{
  static int secret;
public:
  static void callback() { secret = 42; }
};

extern "C" void callback() { MyClass::callback(); }
Run Code Online (Sandbox Code Playgroud)

请注意,对于回调注册点的作者(即,将向您回调的库的作者)来说,为用户提供了一种void*与回调相关联的数据的方法被认为是一种良好的做法,该回调将在他们调用您时传入.如果您的库允许,您可以使用它void *user_data来传递指向C++类的指针.有了这样一个设计精美的回调库,它看起来像这样:

class MyClass
{
  int secret;

public:
  void setSecret() { secret = 42; }
};

extern "C" void callback(void *userData) { static_cast<MyClass*>(userData)->setSecret(); }

MyClass mc;

int main()
{
  cLibrary_registerCallback(&callback, &mc);
}
Run Code Online (Sandbox Code Playgroud)