Callback のサンプル

このサンプルでは、関数ポインターを要求するアンマネージ関数にデリゲートを渡す方法を示します。 デリゲートは、メソッドへの参照を保持できるクラスのことであり、タイプ セーフ関数ポインターまたはコールバック関数と等価です。

メモメモ

呼び出しの中でデリゲートを使用する場合、共通言語ランタイムは、呼び出しの間にデリゲートがガベージ コレクトされないように保護します。ただし、呼び出しが完了した後で使用するためにアンマネージ関数がデリゲートを格納する場合には、アンマネージ関数がデリゲートを終了するまでの間、手動でガベージ コレクションを防ぐ必要があります。詳細については、「HandleRef のサンプル」および「GCHandle のサンプル」を参照してください。

Callback のサンプルで使用するアンマネージ関数とその関数宣言を次に示します。

  • PinvokeLib.dll からエクスポートされる TestCallBack

    void TestCallBack(FPTR pf, int value);
    
  • PinvokeLib.dll からエクスポートされる TestCallBack2

    void TestCallBack2(FPTR2 pf2, char* value);
    

PinvokeLib.dll はカスタム アンマネージ ライブラリであり、上記の関数に関する実装を含みます。

このサンプルでは、LibWrap クラスには TestCallBack メソッドと TestCallBack2 メソッドに関するマネージ プロトタイプが含まれます。 どちらのメソッドも、コールバック関数にパラメーターとしてデリゲートを渡します。 デリゲートのシグネチャは、その参照先メソッドのシグネチャと一致する必要があります。 たとえば、デリゲートの FPtr と FPtr2 は、DoSomething メソッドおよび DoSomething2 メソッドと同じシグネチャを持ちます。

プロトタイプの宣言


Public Delegate Function FPtr( ByVal value As Integer ) As Boolean
Public Delegate Function FPtr2( ByVal value As String[]) As Boolean

Public Class LibWrap
    ' Declares managed prototypes for unmanaged functions.
    Declare Sub TestCallBack Lib "..\LIB\PinvokeLib.dll" ( ByVal cb _
        As FPtr, ByVal value As Integer )

    Declare Sub TestCallBack2 Lib "..\LIB\PinvokeLib.dll" ( ByVal cb2 _
        As FPtr2, ByVal value As String[])
End Class
public delegate bool FPtr(int value);
public delegate bool FPtr2(string value);

public class LibWrap
{
    // Declares managed prototypes for unmanaged functions.
    [DllImport("..\\LIB\\PinvokeLib.dll")]
    public static extern void TestCallBack(FPtr cb, int value);

    [DllImport("..\\LIB\\PinvokeLib.dll")]
    public static extern void TestCallBack2(FPtr2 cb2, String value);
}
public delegate bool FPtr(int value);
public delegate bool FPtr2(String^ value);

public ref class LibWrap
{
public:
    // Declares managed prototypes for unmanaged functions.
    [DllImport("..\\LIB\\PinvokeLib.dll")]
    static void TestCallBack(FPtr^ cb, int value);

    [DllImport("..\\LIB\\PinvokeLib.dll")]
    static void TestCallBack2(FPtr2^ cb2, String^ value);
};

関数の呼び出し

Public Class App
   Public Shared Sub Main()
        Dim cb As FPtr
        cb = AddressOf App.DoSomething
        Dim cb2 As FPtr2
        cb2 = AddressOf App.DoSomething2
        LibWrap.TestCallBack( cb, 99 )
        LibWrap.TestCallBack2( cb2, "abc" )
    End Sub 'Main

    Public Shared Function DoSomething( ByVal value As Integer ) As Boolean
        Console.WriteLine( ControlChars.CrLf + "Callback called with param: {0}", value )
        ' ...
        Return True
    End Function

    Public Shared Function DoSomething2( ByVal value As String[]) As Boolean
        Console.WriteLine( ControlChars.CrLf + "Callback called with param: {0}", value )
        ' ...
        Return True
    End Function
End Class
public class App
{
    public static void Main()
    {
        FPtr cb = new FPtr(App.DoSomething);
        LibWrap.TestCallBack(cb, 99);
        FPtr2 cb2 = new FPtr2(App.DoSomething2);
        LibWrap.TestCallBack2(cb2, "abc");
    }

    public static bool DoSomething(int value)
    {
        Console.WriteLine("\nCallback called with param: {0}", value);
        // ...
        return true;
    }

    public static bool DoSomething2( String value )
    {
        Console.WriteLine("\nCallback called with param: {0}", value);
        // ...
        return true;
    }
}
public ref class App
{
public:
    static void Main()
    {
        FPtr^ cb = gcnew FPtr(&App::DoSomething);
        LibWrap::TestCallBack(cb, 99);
        FPtr2^ cb2 = gcnew FPtr2(&App::DoSomething2);
        LibWrap::TestCallBack2(cb2, "abc");
    }

    static bool DoSomething(int value)
    {
        Console::WriteLine("\nCallback called with param: {0}", value);
        // ...
        return true;
    }

    static bool DoSomething2(String^ value)
    {
        Console::WriteLine("\nCallback called with param: {0}", value);
        // ...
        return true;
    }
};

参照

概念

各種のマーシャリングのサンプル

プラットフォーム呼び出しのデータ型

マネージ コードでのプロトタイプの作成