C++ idiom when using a C library which expects a function pointer?
我在C++应用程序中使用C库。c sdk具有将回调函数指针作为参数的函数。这些函数的签名通常如下:
1 | typedef int (* Func) (type1 c, type2 d); |
我的代码是用C++中的类构造的。但是,我不能将任何成员函数作为回调传递给这个函数,因为它不接受
我通过在不同的类中将所有回调定义为
我对C++仍然是新的,所以我不确定这是不是正确的解决方案?代码有效,但如果我做错了,我很想听听。
在您的代码可能遇到的大多数平台上,您的解决方案都很好。但是,严格来说,可以有一个C调用约定和C++调用约定不同的平台。在这个平台上,您的代码将不起作用。
100%正确的解决方案(与您使用的99.9%正确的解决方案相反)是定义一个带有C语言链接的函数作为回调。如果您需要此函数让成员访问您的类,那么它可以调用您的类中的
1 2 3 4 5 6 7 8 | class MyClass { static int secret; public: static void callback() { secret = 42; } }; extern"C" void callback() { MyClass::callback(); } |
请注意,对于回调注册点的作者(即将回拨您的库的作者)来说,这是一个很好的实践,可以为用户提供一种将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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对
要将非静态成员函数作为回调调用,需要定义一个以实例为参数的非成员函数,并在该实例上调用成员函数。使用函数指针回调的此类C API还允许注册指向用户定义数据的空指针,该数据将被转发到回调。使用此指针传递实例。
通常使用lambda而不是命名函数,因为这种简单的包装器通常不可重用,也不需要名称。