我在使用C音频库(使用ASIO SDK内置的PortAudio,但是与这个问题并没有真正的联系;技术细节只会妨碍我提出这个问题)时遇到问题.
简而言之,该库中的某个C函数要求我给它提供一个回调函数,该回调函数返回某个值并接受某些参数.为了清楚起见,假设回调应如下所示:
int callback(int arg)
对库函数的调用如下所示:
theCLibraryFuntion(foo, bar, callback);
像这样使用库(即以过程C风格的方式)可以很好地工作,但我想将与我相关的库功能包装在结构良好的C类中.我需要的库项目是迄今为止我最大的工作,因此面向对象设计对我来说是必须的.我想在C中创建一个抽象类,为派生类提供一个纯虚函数以实现,然后让知道该库的类将该实现用于回调.换句话说,我需要实际的多态性,而不是讨厌的函数指针.
到目前为止,我还无法编写此类.编译器不允许我将任何类的非静态成员函数作为回调传递给C库函数.我知道为什么,但是我想知道一些解决方法.只要存在该变通办法,只要它能够为前端类提供多态行为,我就不在乎后端代码变得多么邪恶.如果不存在这样的解决方法,那就去吧.我非常了解C在后台的工作方式,但是我对C中的OO功能的技术了解甚少,所以我将假设有一种方法.
提前致谢!
注意:一种可能会增加大量开销的解决方法对我来说可能毫无价值.我*使用此C portaudio库,因为它是唯一使我的项目所需的音频流延迟极短的API,因此,大幅增加开销并不是真正的选择.
解决方法:
您的代码过于简化.在现实世界中,“库函数”和回调都将具有void *“用户数据”参数.您可以将指向类实例的指针传递到“库函数”的“用户数据”中,并将其转发到回调中,您可以在其中使用该指针访问对象.
class CallbackImplBase {
public:
virtual void CallbackImpl() = 0;
static void CallbackToPass( void* userData )
{
static_cast<CallbackImplBase*>(userData)->CallbackImpl();
}
};
class ActualCallbackImpl : public CallbackImplBase {
void CallbackImpl() { //implemented here }
};
ActualCallbackImpl callback;
callLibraryFunction( params,
&CallbackImplBase::CallbackToPass, static_cast<CallbackImplBase*>( &callback ) );
请注意“ library function”调用的最后一个参数附近的static_cast.除非您具有多个继承,否则您将不需要它,但无论如何它仍然存在.