在C ++抽象类中实现回调(对于C库)为纯虚拟

我在使用C音频库时遇到了问题(使用ASIO SDK构建的PortAudio,但这与这个问题并不相关;技术细节只会妨碍我提出这个问题)

简单地说,来自该库的某个C函数需​​要我给它一个回调函数,该函数返回一个值并接受某些参数; 为了清楚起见,让我们说回调应该是这样的:

int callback(int arg) 

并且对库函数的调用如下所示:

 theCLibraryFuntion(foo, bar, callback); 

使用这样的库(即以程序C风格的方式)工作正常,但我想在结构良好的C ++类中包装与我相关的库函数。 我需要图书馆的项目是迄今为止我所做过的最大的项目,所以OO-design对我来说是必须的。 我想在C ++中创建一个抽象类,它为要实现的派生类提供纯虚函数,然后让这个实现用于知道库的类的回调。 换句话说,我需要实际的多态性而不是令人讨厌的函数指针。

到目前为止,我还没能写出这样的课程。 编译器不允许我将任何类的非静态成员函数作为回调传递给C库函数。 我理解为什么,但我想知道一些解决方法。 只要该解决方法,如果它存在,给我前端类的多态行为,我不关心后端代码变得多么邪恶。 如果不存在这样的解决方法,那就这样吧。 我非常了解C在后台如何工作,但我对C ++中OOfunction的技术性知之甚少,因此我将假设有一种方法。

提前致谢!

注意:一个会增加大量开销的解决方法对我来说可能毫无价值。 我被迫使用这个C portaudio库,因为它是唯一一个能够为我的项目所需的音频流提供极低延迟的API,因此大幅度增加开销并不是一个真正的选择。

您的代码过于简单了。 在现实世界中,“库函数”和回调都将具有void* “user data”参数。 您可以将指向类实例的指针传递给“库函数”的“用户数据”,它将被转发到回调中,您可以使用该指针访问该对象。

 class CallbackImplBase { public: virtual void CallbackImpl() = 0; static void CallbackToPass( void* userData ) { static_cast(userData)->CallbackImpl(); } }; class ActualCallbackImpl : public CallbackImplBase { void CallbackImpl() { //implemented here } }; ActualCallbackImpl callback; callLibraryFunction( params, &CallbackImplBase::CallbackToPass, static_cast( &callback ) ); 

请注意“库函数”调用的最后一个参数附近的static_cast 。 你不需要它,除非你有多重inheritance,它仍然存在。

据我所知,PortAudio中的回调(如此回调)采用void*参数将用户数据传递给它们。 您可以使用它来通过将类指针作为用户数据传递来调用成员函数,并编写一个小的静态或非成员函数来注册为C兼容的回调。 例如:

 // C library function typedef void (*c_library_callback)(void * user_data); void c_library_start_stuff(c_library_callback, void * user_data); // C++ class using it class audio_thing { public: virtual ~audio_thing() {} // Better have one of these in an abstract class void start_stuff() { c_library_start_stuff(&audio_thing::static_callback, this); } private: // C-compatible callback forwards to the implementation static void static_callback(void * thing) { static_cast(thing)->callback(); } // Derived classes implement the callback behaviour virtual void callback() = 0; };