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 」と一致しません、AudioBufferList*)

4

4 に答える 4

2

これを行うために静的インスタンスをいじる必要はありません。render コールバックを追加するときは、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

APIデザイナーがあなたに素晴らしいトリックを提供したので sboothの答えはここでのアンサーです。ただし、コールバックを適切に設計されていない C ライブラリに渡していた場合は、以下の回答が役立つ場合があります。

メンバー関数へのポインターから関数へのポインターに取得する必要があります。

c++ faq lite herehereに答えがあります

次のいずれかを実行できます。

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::bind がこれを実行できます。

于 2011-07-14T04:24:26.027 に答える