コールバック メソッドとしてのデリゲートのマーシャ リングMarshaling a Delegate as a Callback Method

このサンプルでは、関数ポインターを要求するアンマネージ関数にデリゲートを渡す方法を示します。This sample demonstrates how to pass delegates to an unmanaged function expecting function pointers. デリゲートは、メソッドへの参照を保持できるクラスであり、タイプ セーフな関数ポインターまたはコールバック関数と同等のものです。A delegate is a class that can hold a reference to a method and is equivalent to a type-safe function pointer or a callback function.

注意

呼び出しの中でデリゲートを使うと、共通言語ランタイムがデリゲートをその呼び出しの期間中ガベージ コレクションから保護します。When you use a delegate inside a call, the common language runtime protects the delegate from being garbage collected for the duration of that call. ただし、アンマネージ関数が呼び出し完了後に使うためにデリゲートを保存する場合は、アンマネージ関数がデリゲートを終了するまで手動でガベージ コレクションを防ぐ必要があります。However, if the unmanaged function stores the delegate to use after the call completes, you must manually prevent garbage collection until the unmanaged function finishes with the delegate. 詳細については、「HandleRef Sample」(HandleRef のサンプル) および「GCHandle Sample」(GCHandle のサンプル) をご覧ください。For more information, see the HandleRef Sample and GCHandle Sample.

Callback のサンプルで使用するアンマネージ関数とその元の関数宣言を次に示します。The Callback sample uses the following unmanaged functions, shown with their original function declaration:

  • PinvokeLib.dll からエクスポートされる TestCallBackTestCallBack exported from PinvokeLib.dll.

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

    void TestCallBack2(FPTR2 pf2, char* value);  
    

PinvokeLib.dll はカスタム アンマネージ ライブラリであり、上で示した関数の実装を含んでいます。PinvokeLib.dll is a custom unmanaged library that contains an implementation for the previously listed functions.

このサンプルでは、LibWrap クラスには、TestCallBack メソッドと TestCallBack2 メソッドのマネージド プロトタイプが含まれます。In this sample, the LibWrap class contains managed prototypes for the TestCallBack and TestCallBack2 methods. どちらのメソッドも、コールバック関数にパラメーターとしてデリゲートを渡します。Both methods pass a delegate to a callback function as a parameter. デリゲートのシグネチャは、それが参照しているメソッドのシグネチャと一致する必要があります。The signature of the delegate must match the signature of the method it references. たとえば、FPtr および FPtr2 デリゲートのシグネチャは、DoSomething および DoSomething2 メソッドと同じです。For example, the FPtr and FPtr2 delegates have signatures that are identical to the DoSomething and DoSomething2 methods.

プロトタイプの宣言Declaring Prototypes

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 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 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

関数の呼び出しCalling Functions

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;
    }
};
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 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

関連項目See also