1

Fooパラメータとして2パラメータ関数を取る関数があります:

void Foo(void (*fcn)(int, int*));

ただし、 ( ) で渡したい関数の型は、func1 つのパラメーターのみを取ります*

typedef void (__stdcall *FuncCallBack)(int a);

void Caller(FuncCallBack func) {
   Foo(????);
}

C# では、次のようにします。

Foo((a,b) -> func(a));

デリゲート クラスで同様のことをしようとしています (バインドされたメンバー関数へのポインターを持つことができないことがわかったので、静的に切り替えました):

class Delegate {
private:
 static FuncCallBack _Callback;
public
 Delegate(FuncCallBack);
 static void Callback(int, int*);
}

Delegate::Delegate(FuncCallback callback) { _Callback = callback; }

void Delegate::Callback(int a, int *b) { _Callback(a); }

私は次のように使用します:

void Caller(FuncCallBack func) {
   Delegate d = Delegate(func);
   Foo(&(d.Callback));
}

現在、これによりリンカーエラーが発生しています:unresolved external symbol "private: static void (__stdcall* Delegate::_Callback)(int)" (?_Callback@Delegate@@0P6GXHHPAN0@ZA)

  • 質問 1: このリンカ エラーの原因は何ですか?
  • 質問 2: これを行うためのより良い方法はありますか?

*関数 typedef は__stdcall、C# から渡される (そして C# にコールバックする) ため、インクルードされます)。

4

2 に答える 2

2

コメントで指摘したように、クラスを使用すると、コールバック関数をクラス インスタンスにラップしたように見えますが、コールバック関数は生の関数ポインタであるため、クラス インスタンスから元の状態にアクセスすることはできません。から得られました。静的メンバー変数にのみアクセスできます。これは、新しいインスタンスが構築されるたびに、すべてのインスタンスの動作が変わることを意味します。 DelegateDelegate

別の呼び出しをサポートする必要がある場合はfunc、コールバック関数のみが一度にアクティブになるという事実をインターフェイスからより明確にする、より単純なインターフェイスを使用します。

例えば:

callbackwrapper.h:

void CallbackWrapper(int, int*);
void SetWrappedCallback(void (__stdcall *toWrap)(int));

callbackwrapper.cpp:

namespace {
    void (__stdcall *wrappedCallback)(int);
}

void CallbackWrapper(int a, int*)
{
    wrappedCallback(a);
}

void SetWrappedCallback(void (__stdcall *toWrap)(int))
{
    wrappedCallback = toWrap;
}
于 2012-06-04T10:41:18.843 に答える
2

クラスのメンバーを一度だけ定義する必要がありますstatic(たとえば、Delegate.cpp で):

FuncCallBack Delegate::_Callback;

投稿されたコードでは、 の宣言のみがあり_Callbackます。

于 2012-06-04T10:04:58.713 に答える