C 习语使用C库时,该C库期望功能指针

C++ idiom when using a C library which expects a function pointer?

本文关键字:期望 功能 指针 习语 库时      更新时间:2023-10-16

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

typedef int (* Func) (type1 c, type2 d);

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

我通过将所有回调定义为各个类中的static,然后将它们传递到CC库中,然后将其传递到CC_3。

我仍然是C 的新手,所以我不确定这是正确的解决方案吗?该代码有效,但我很想听听我是否做错了。

在大多数平台上,您的代码可能遇到,您的解决方案很好。但是,严格来说,可以有一个平台,C呼叫约定和C 调用约定也有所不同。在此平台上,您的代码无法正常工作。

100%正确的解决方案(与您使用的99.9%正确的解决方案相反)是定义具有C语言链接的函数作为回调。如果您需要此功能以使会员访问您的课程,则可以在您的课程中调用static成员函数:

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

请注意,对于回调注册点的作者(即库的作者,将回电给您)是很好的做法他们打电话给你。如果您的库允许,则可以使用此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);
}

成员函数总是隐含地将'this'作为他们的第一个参数。静态功能的使用通常可以用作静态函数,不需要此隐式参数。请查看ANGEW的答案,其中包括extern "C"的东西,以获得100%的可移植性。

要调用非静态成员函数作为回电,您需要定义非成员函数,该函数将实例作为参数,并在该实例上调用成员函数。使用函数指针回调的C API还允许注册一个可以转发回通话的用户定义的数据的空隙指针。使用此指针通过实例。

而不是命名函数,是使用lambda的典型特征,因为这种简单的包装器通常不可重复使用,并且不需要名称。