如何在封装在类中的回调函数上发送指针
Posted
技术标签:
【中文标题】如何在封装在类中的回调函数上发送指针【英文标题】:How to send a pointer on a callback function which is encapsulated in a class 【发布时间】:2011-11-28 20:58:56 【问题描述】:我实际上是在使用库 PortAudio 用 C++ 编写程序。 该库使用回调函数来管理音频输入和输出。 在 C++ 中,我在我的“音频”类中实现了这个回调函数,但我无法将它发送到 Pa_OpenDefaultStream()。编译器用这一行说“这个参数与 PaStreamCallback* 类型的参数不兼容”:
Pa_OpenDefaultStream(&this->_stream, 1, 2, paFloat32, this->_sampleRate, this->_framesPerBuffer, callbackFunction, NULL);
当我使用 C 时,像这样发送我的 callbackFunction 效果很好。 如何将我的回调函数发送到这个 OpenDefaultStream 函数?
【问题讨论】:
PaStreamCallback* 的签名是什么? 重复***.com/questions/8256142/… 好的,非常感谢你们。我使用静态关键字,它可以工作,但我不能使用“this”关键字。 【参考方案1】:您需要实现一个与 PaStreamCallback 具有相同签名的普通全局函数。
看起来 PaStreamCallback 需要一个参数 void* userData。这就是通常所说的上下文参数。如果不了解 PortAudio,我猜您可以使用它来表示您的类实例。当您调用 Pa_OpenDefaultStream 时,将“this”传递给 userData 指针,您在示例中写的是 NULL。
这是您需要的函数包装器的示例实现:
int MyPaStreamCallback (const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
MyClass *myClass = reinterpret_cast<MyClass*>(userData);
return myClass->callbackFunction(input, output, frameCount, timeInfo, statusFlags);
然后将您的原始代码替换为:
Pa_OpenDefaultStream(&this->_stream, 1, 2, paFloat32, this->_sampleRate, this->_framesPerBuffer, MyPaStreamCallback , this);
我假设你会让你的 callbackFunction 获取所有其他参数。
【讨论】:
【参考方案2】:当您有机会传递“用户数据”或上下文时,Erik Olson 的答案非常有用。如果这是不可能的,你可能需要一个丑陋的黑客来从回调中获取你的 this 指针。我已经看到带有回调的类也有这个指针的静态副本,只有当你只有一个类的实例时才会起作用。 Ugggggly,但它的工作原理。
这种丑陋是所有 API 都有一个优雅的方式来处理这个问题的论据,理想情况下,使用重新解释强制转换不会破坏类型安全。
【讨论】:
【参考方案3】:我知道已经有一段时间了,但我遇到了同样的问题并找到了 C++11 风格的解决方案。
所以我们有
int AudioHandler::CallBackFunction(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData);
那么,AudioHander.cpp 中哪里做全局变量:
AudioHandler* veryDangerousHandler;
最后:
PaStreamCallback* callbackus = [](const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData) -> int
return veryDangerousHandler->CallBackFunction(inputBuffer, outputBuffer,
framesPerBuffer,
timeInfo,
statusFlags,
userData);
;
【讨论】:
以上是关于如何在封装在类中的回调函数上发送指针的主要内容,如果未能解决你的问题,请参考以下文章