2


0

デリゲートの問題

これは、Cコードからアンマネージ関数を呼び出すために作成しました。 pCallbackは関数ポインターであるため、管理対象側はデリゲートです。

[DllImport("MyDLL.dll")]

public static extern Result SetCallback(
            IntPtr handle,
            Delegate pCallback,
            CallbackType Type);

今私は設定しています

    public delegate void pfnCallback(uint PromptID, ttsEventType evt, IntPtr lData);

    public Form1()
    {
        pfnCallback cb = new pfnCallback(cback);
        (...)
        Wrapper.SetCallback(handle, cb, IntPtr.Zero, CallBackType.DEFAULT);
        (...)
        }

「…​」というエラーが表示されます デリゲートをアンマネージコードに渡すとき、それらは生き続ける必要があります…​ "

誰かが私を手伝ってくれる?

よろしく

4 Answer


3


メッセージを理解している限り、次のようにする必要があります。

public delegate void pfnCallback(uint PromptID, ttsEventType evt, IntPtr lData);

public pfnCallback cb = new pfnCallback(cback);

public Form1()
{
    (...)
    Wrapper.SetCallback(handle, cb, IntPtr.Zero, CallBackType.DEFAULT);
    (...)
}


3


アンマネージコードが呼び出したい限り、変数が存在し続け、コールバック関数を参照するように、cbのスコープを拡張する必要があると思います。 アンマネージコードは.NET参照の追跡に参加しないため、コールバックへの参照を.NETコードに保持しなければ、フレームワークによって解放され、アンマネージコードはその後適切に呼び出すことができませんそれ。


2


デリゲートの型宣言とデリゲートのインスタンスを混同しています。 はい、デリゲート宣言を公開しましたが、それは間違っていました。 Form1クラスのみがそれを使用します。プライベートでなければなりません。 ここで重要なのはデリゲートのインスタンスであり、新しいステートメントで作成したものです。

現時点では、インスタンスをForm1コンストラクターのローカル変数に格納しています。 これにより、インスタンスの参照が数マイクロ秒保持されます。 コンストラクターが完了するとすぐに、その参照はなくなり、ガベージコレクターはその後いつでもデリゲートインスタンスを収集できます。 アンマネージコードがそれへの参照を保持していることがわかりません。コレクターは、マネージコードが保持している参照のみを検出できます。

アンマネージコードが収集されたデリゲートインスタンスでコールバックを呼び出すと、何も起こりません。大きなカブームが聞こえます。 インスタンスへの管理参照があるようにコードを変更する必要があります。 これを行う簡単な方法の1つは、インスタンスを格納するプライベートメンバーをForm1クラスに追加することです。

十分ではないかもしれませんが、Form1オブジェクトは将来のある時点でガベージコレクションされます。 デリゲートオブジェクトも収集します。 また、アンマネージコードが発生した後にコールバックを使用できないことを確認する必要があります。 クラスの名前(Form1)が与えられると、この特定のケースでは起こりそうにありません。 ただし、防御的にコーディングし、フォームのFormClosingイベントハンドラーでコールバックをリセットする呼び出しを行います。


0


コールバック変数 `cb`をグローバルに試してください