C3374:デリゲートインスタンスを作成しない限り、「関数」のアドレスを取得できません

StackOverflow https://stackoverflow.com/questions/822582

  •  03-07-2019
  •  | 
  •  

質問

サードパーティのライブラリ登録関数を使用してコールバックを登録するのが困難です。C++ CLI で記述しており、C または C++ で記述されたライブラリにアクセスしています。

上記のコンパイラエラーは何を意味するのでしょうか?

これはベンダーによって定義された登録関数です。

MYCO int WINAPI MyCo_Device_Register_CallbackFunc(LPVOID func, LPVOID lpParam, DWORD mask);

これはベンダーによって定義されたコールバックです。

typedef void (CALLBACK* MyCo_Device_CallbackProc)(DWORD ddStatus, LPVOID lpParam);

私のコールバック関数:

public ref class Device 
{
    void CallBackFunc(DWORD ddStatus, LPVOID lpParam) {};
}

私の呼び出し(失敗):

MyCo_Device_Register_CallbackFunc((LPVOID) Device::CallBackFunc, nullptr, 0xFFFF);
役に立ちましたか?

解決

推測を行わなければならなかった場合、管理対象関数のアドレスを取得し、それをネイティブ関数ポインターとして渡そうとしています。それはまったく機能しません。ネイティブブリッジを作成するか(より難しく、おそらく利点がない)、または(これがより簡単なアプローチです)、デリゲートを作成して Marshal.GetFunctionPointerForDelegate 。デリゲートは、ネイティブコードがコールバックする予定の期間、生き続ける必要があることを忘れないでください。そのため、おそらくどこかに保存する必要があります。

ああ、refクラスまたはvalueクラス内のすべての関数は、明確でない場合に備えてマネージ関数です。

[編集]回答を拡大してコメントの質問をカバーします。最初のステップは、一致するデリゲートを作成することです。指定した関数については、次のようになります。

public delegate void CallbackFuncDelegate(DWORD ddStatus, LPVOID lpParam);

次に、作成する必要があります:

CallbackFuncDelegate del = gcnew CallbackFuncDelegate(CallbackFunc);

前述のように、クラスが消失しないことを確認するために、そのINをメンバーとして保存する必要があります。最後に、関数ポインタを取得して渡す必要があります。

MyCo_Device_Register_CallbackFunc((MyCo_Device_CallbackProc) Marshal::GetFunctionPointerForDelegate(del).ToPointer(), 0, 0);

これですべてがカバーされると思います。名前空間システムを使用するだけです。大丈夫です。

他のヒント

コールバック関数はメンバーです。メンバーへのポインターと関数へのポインターは別のものです。

Promit のソリューションでも次のようになります。

CallbackFuncDelegate(CallbackFunc)

CallbackFunc をクラス メンバーにすることはできません

シンプルに書くこともできます

public ref class Device 
{
    static void CallBackFunc(DWORD ddStatus, LPVOID lpParam) {};
}

そして使用します

Device::CallBackFunc
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top