2

我实际上正在使用库 PortAudio 用 C++ 编写程序。该库使用回调函数来管理音频输入和输出。在 C++ 中,我在我的“音频”类中实现了这个回调函数,但我无法将它发送到 Pa_OpenDefaultStream()。编译器用这一行说“这个参数与 PaStreamCallback* 类型的参数不兼容”:

Pa_OpenDefaultStream(&this->_stream, 1, 2, paFloat32, this->_sampleRate, this->_framesPerBuffer, callbackFunction, NULL);

当我使用 C 时,像这样发送我的 callbackFunction 效果很好。如何将我的回调函数发送到此 OpenDefaultStream 函数?

4

3 回答 3

3

您需要实现一个与 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 获取所有其他参数。

于 2011-11-28T21:13:02.500 回答
0

当您有机会传递“用户数据”或上下文时,Erik Olson 的答案非常有用。如果这是不可能的,你可能需要一个丑陋的黑客来从回调中获取你的 this 指针。我已经看到带有回调的类也有这个指针的静态副本,只有当你只有一个类的实例时才会起作用。Ugggggly,但它的工作原理。

这种丑陋是所有 API 都有一个优雅的方式来处理这个问题的论据,理想情况下,使用 reinterpret cast 不会破坏类型安全。

于 2014-01-17T02:20:35.273 回答
0

我知道已经有一段时间了,但我遇到了同样的问题并找到了 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);
};
于 2014-08-15T06:04:44.563 回答