C++;使用需要函数指针的C库时的习惯用法? 我在C++应用程序中使用C库。C SDK具有将回调函数指针作为参数的函数。这些函数的签名通常类似于: typedef int (* Func) (type1 c, type2 d); 我用C++中的类构造了我的代码。但是,我无法将任何成员函数作为回调传递给此函数,因为它不接受int(MyClass::*)(Type1c,Type2d),只接受int(*)(Type1c,Type2d)

C++;使用需要函数指针的C库时的习惯用法? 我在C++应用程序中使用C库。C SDK具有将回调函数指针作为参数的函数。这些函数的签名通常类似于: typedef int (* Func) (type1 c, type2 d); 我用C++中的类构造了我的代码。但是,我无法将任何成员函数作为回调传递给此函数,因为它不接受int(MyClass::*)(Type1c,Type2d),只接受int(*)(Type1c,Type2d),c++,C++,我通过在各种类中将所有回调定义为static,然后将它们传递给C库来解决这个问题 我对C++还很陌生,所以我不确定这是不是正确的解决方案?代码可以工作,但我很想知道我是否做得不对。要将非静态成员函数作为回调调用,需要定义一个非成员函数,该函数将实例作为参数,并在该实例上调用成员函数。这种使用函数指针回调的C API还允许注册指向用户定义数据的无效指针,这些数据将被转发到回调。使用此指针传递实例 通常使用lambda来代替命名函数,因为这样的简单包装器通常不可重用,也不需要名称。成员函数总是隐式地

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


我对C++还很陌生,所以我不确定这是不是正确的解决方案?代码可以工作,但我很想知道我是否做得不对。

要将非静态成员函数作为回调调用,需要定义一个非成员函数,该函数将实例作为参数,并在该实例上调用成员函数。这种使用函数指针回调的C API还允许注册指向用户定义数据的无效指针,这些数据将被转发到回调。使用此指针传递实例


通常使用lambda来代替命名函数,因为这样的简单包装器通常不可重用,也不需要名称。

成员函数总是隐式地将“this”作为其第一个参数。静态函数的使用通常起作用,因为静态函数不需要这个隐式参数。请使用
extern“C”
thing查看Angew的答案,以获得100%的可移植性

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

100%正确的解决方案(与您使用的99.9%正确的解决方案相反)是定义一个带有C语言链接的函数作为回调函数。如果您需要此函数对类进行成员访问,则它可以调用类中的
静态
成员函数:

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

extern "C" void callback() { MyClass::callback(); }

请注意,回调注册点的作者(即将回叫您的库的作者)可以为用户提供一种方法,将
void*
数据与回调关联起来,这被认为是一种良好的做法,当用户调用您时,这些数据将被传入。如果你的库允许,你可以使用这个代码> Vult*UsRoDATA < /COD>传递一个指向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);
}
class-MyClass
{
int秘密;
公众:
void setSecret(){secret=42;}
};
extern“C”void回调(void*userData){static_cast(userData)->setSecret();}
MyClass mc;
int main()
{
cLibrary_registerCallback(&callback,&mc);
}

< /Cordal> C回调应该使用<代码> VultUSELDATA <代码>允许使用C++类。@ ThomasSablik将如何增强。绑定帮助与C回调;非成员函数应该标记为代码>外“C”< /代码>。C++函数不需要使用与C函数相同的调用约定,因此,正如其他答案指出的,为了最大可移植性,回调应该是非成员函数,标记为<代码> Extn“C”<代码>。@ PeeBekk是的,您是对的。我编辑了答案以反映这一点。谢谢!在我明白发生了什么之前,我花了相当多的时间思考。SDK中的一些函数确实有void*,但我没有以正确的方式使用它们。接下来的问题是,如果我想把一个参数传递给回调函数,我会怎么做。例如,在第二个示例中,如果我想将
字符串
传递给
setSecret
,即
static_cast(userData)->setSecret(“Hello”)?@PlastyGrove
setSecret
在第二个示例中完全由您控制,您可以使用它做任何您想做的事情。
callback
的签名由库(调用它的人)指定。如果需要在回调旁边存储一些数据(以便回调在调用时接收数据),则必须使其成为
userData
的一部分。例如,让
userData
指向的不是
MyClass
,而是
std::pair
或类似的东西(当然,要正确管理它的生命周期)。我明白了,让我来试一试。我想我必须创建几个成员级
std::pair
变量,并在将其传递给回调寄存器函数之前分配
this
。谢谢