0

我的 C++ 技能很轻,但我设法完成了工作——直到我碰壁。现在的墙:

我正在使用 CoreAudio 来做一些关于 Midi 播放的事情。我有很多工作,但被困在一个简单的事情上。(我不知道正确的 C++ 术语,所以请耐心等待......)。

我在 CoreAudio 中使用渲染回调函数来指示 AU 何时渲染 midi 音符事件。如果我将它定义为非类函数并将其粘贴到 main.cpp (或 testApp.cpp ),它就可以工作 - 我得到了事件。问题是我需要能够让 testApp 的实例获取这些事件。

所以..有没有办法从 main.cpp 获取 testApp 的实例,这样我就可以调用我需要的 testApp 方法?

或者是否有一些 C++ 巫术让一个非类函数驻留在类中调用实例的方法?例如,如果下面的函数在我的类中,它如何调用类的实例上的方法......

    OSStatus renderCallback(void *inRefCon,
                                              AudioUnitRenderActionFlags *  ioActionFlags,
                                              const AudioTimeStamp *        inTimeStamp,
                                              UInt32                inBusNumber,
                                              UInt32                inNumberFrames,
                                              AudioBufferList *     ioData)
{

           someClassMethod(); // doesn't work
           this.someClassMethod(); // doesn't work
           self.someClassMethod(); // doesn't work

}

我不确定,但我认为 CoreAudio 的东西不会将实例方法作为回调 - 至少这是我从错误消息(如下)中收集到的。无论如何,我很好地做到了。

感谢您的任何提示!

错误:OSStatus (testApp::)(void*, AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32, UInt32, AudioBufferList*)' 类型的参数不匹配 'OSStatus ( )(void , AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32, UInt32 , 音频缓冲区列表*)

4

4 回答 4

2

你不需要弄乱静态实例来做到这一点。添加渲染回调时,将 C++ 对象作为 refcon 传递,然后将 refcon 强制转换为回调中的对象:

// The actual callback is defined as a static function
static OSStatus
myAURenderCallback(void *inRefCon, 
                   AudioUnitRenderActionFlags *ioActionFlags,
                   const AudioTimeStamp *inTimeStamp,
                   UInt32 inBusNumber,
                   UInt32 inNumberFrames,
                   AudioBufferList *ioData)
{
    MyClass *object = static_cast<MyClass *>(inRefCon);
    return object->Render(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
}


// When adding the render callback pass this as the context
AURenderCallbackStruct cbs = { myAURenderCallback, this };
OSStatus result = AUGraphSetNodeInputCallback(graph, node, 0, &cbs);


// The callback will look like
OSStatus MyClass::Render(AudioUnitRenderActionFlags *ioActionFlags,
                         const AudioTimeStamp *inTimeStamp,
                         UInt32 inBusNumber,
                         UInt32 inNumberFrames,
                         AudioBufferList *ioData)
{
  // Do something
}
于 2011-07-14T04:34:23.343 回答
0

sbooth 的答案是这里答案,因为 api 设计者为您提供了一个不错的技巧。但是,如果您将回调传递给设计不太好的 c 库,那么下面的答案可能会有所帮助。

您需要从指向成员函数的指针到指向函数的指针。

此处此处的 c++ faq lite有您的答案

您可以:

1.将 someMethod() 设为静态并保留 testApp 的静态实例(如果您需要旋转实例数据) 2.全局存储一个 testApp 指针并从您已经使用的全局函数中使用它

这是我推荐的方法 1的示例

class Test
{
public:
    Test();
    void InstanceCallback();
    static void StaticCallbackMethod();

private:
    static Test* instance;
};


// Normally in cpp
Test* Test::instance = 0;

Test::Test()
{
    instance = this;
}

void Test::InstanceCallback()
{
    // do stuff;
}

void Test::StaticCallbackMethod()
{
    if (instance)
    {
        instance->InstanceCallback();
    }
}

int main()
{
    Test* t = new Test();

    void (*mf)();
    mf = &Test::StaticCallbackMethod;   
    mf();

    return 0;
}

鉴于您对 c++ 的了解程度,我真的建议您先阅读所有faq lite,然后再阅读fqa。我希望有人在我开始时向我推荐它。

于 2011-07-14T03:04:09.320 回答
0

您是正确的,您不能在此处使用指向实例方法的指针(无法提供指向成员函数的隐式“this”指针,因为实际上并未通过对象调用回调)。

您可以为此使用静态成员函数(然后您需要某种方式为该函数提供指向您的 testApp 实例(全局变量、静态实例等)的指针)。

于 2011-07-14T03:10:06.720 回答
0

如果你可以安装 boost,boost::bind 可以为你做这件事。

于 2011-07-14T04:24:26.027 回答