3

関数ポインターをコールバックとして渡す必要がある API を使用しています。C++ のクラスからこの API を使用しようとしていますが、コンパイル エラーが発生します。

API 定義は次のとおりです。

typedef void (__stdcall *STREAM_CALLBACK)(void *userdata);

__declspec(dllimport) int __stdcall set_stream_callback(
    STREAM_CALLBACK streamCB, void *userdata);

サードパーティが提供するファイルの例は次のとおりです。

void __stdcall streamCB(void *userdata)
{
  // callback implementation
}

int main(int argc, const char argv[])
{
  int mid = 0;
  set_stream_callback(streamCB, &mid);
}

そして、それはうまくいきます。ただし、クラスでそれを使用しようとすると、エラーが発生します。

エラー C3867: 'MyClass::streamCB': 関数呼び出しに引数リストがありません。「&MyClass::streamCB」を使用して、メンバーへのポインターを作成します

使用する提案

&MyClass::streamCB

動作しません。set_stream_callback は非メンバー関数のみを受け入れることを理解しました。

この問題は、クラス メンバー関数をコールバックとして渡すにはどうすればよいですか?とよく似て います。 その中でヨハネスは簡潔な提案をしているが、私はそれをよく理解していない. この質問に関連していると私が正しければ、誰かが少し拡張できますか?

私が試してみました:

void __stdcall MyClass::streamCB(void *userdata)
{
  // callback implementation
}

static void MyClass::Callback( void * other_arg, void * this_pointer ) {
    MyClass * self = static_cast<ri::IsiDevice*>(this_pointer);
    self->streamCB( other_arg );
}

//and in the constructor
int mid = 0;
set_stream_callback(&MyClass::Callback, &mid);

しかし

エラー C2664: 'set_stream_callback': パラメーター 1 を 'void (__cdecl *)(void *,void *)' から 'STREAM_CALLBACK' に変換できません

どうすればこれを回避できますか?


userdataEdit1:また、コールバック内で使用したいstreamCB

4

2 に答える 2

4

非メンバー関数のみを取得するコールバックからメンバー関数を呼び出すという考え方は、メンバー関数のラッパーを作成することです。ラッパーはどこかからオブジェクトを取得し、メンバー関数を呼び出します。コールバックが適切に設計されている場合は、オブジェクトを識別するために使用する「ユーザーデータ」を渡すことができます。残念ながら、あなたはクラスの詳細を省略しているので、次のようになっていると思います。

class MyClass {
public:
    void streamCB() {
         // whatever
    }
    // other members, constructors, private data, etc.
};

これにより、次のようにコールバックを設定できます。

void streamCBWrapper(void* userData) {
    static_cast<MyClass*>(userData)->streamCB()
}

int main() {
    MyClass object;
   set_stream_callback(&streamCBWrapper, &object);
   // ...
}

関数の作成方法で遊ぶことができるさまざまなゲームがありますstreamCBWrapper(たとえば、staticクラスのメンバーにすることができます)が、すべて同じになります。ユーザーデータからオブジェクトを復元し、メンバー関数を呼び出す必要があります。このオブジェクト。

于 2012-10-29T21:09:28.947 に答える
2

ユーザーデータを MyClass のプロパティに変換することで、目的を達成できます。その後、それを MyClass::Callback に渡す必要はありません。渡すことができるパラメーターは 1 つだけであり、それはオブジェクト インスタンスになるため、これは不可能です。これが例です。

void __stdcall MyClass::streamCB()
{
  // callback implementation
}

static void MyClass::Callback(void * this_pointer ) {
    MyClass * self = static_cast<MyClass>(this_pointer);
    self->streamCB();
}

MyClass::MyClass(void *userdata) {
    // do whatever you need to do with userdata
    // (...)
    // and setup the callback at C level
    set_stream_callback(&MyClass::Callback, (void *)this);
}

あなたの例では、int mid変数はそのクラスのプロパティになるため、コールバック実装からアクセスできますstreamCB

于 2012-10-29T21:04:38.210 に答える