Beispiel zu Callbacks

Dieses Beispiel demonstriert, wie Delegaten an eine nicht verwaltete Funktion übergeben werden, die Funktionszeiger erwartet. Ein Delegat ist eine Klasse, die einen Verweis auf eine Methode enthalten kann und einem typsicheren Funktionszeiger oder einer Rückruffunktion entspricht.

HinweisHinweis

Wenn Sie einen Delegaten in einem Aufruf verwenden, verhindert die Common Language Runtime für die Dauer des Aufrufs, dass für den Delegaten eine Garbage Collection durchgeführt wird.Wenn die nicht verwaltete Funktion den Delegaten für die Verwendung nach Abschluss des Aufrufs speichert, müssen Sie die Garbage Collection manuell verhindern, bis die nicht verwaltete Funktion mit dem Delegaten beendet wird.Weitere Informationen finden Sie im HandleRef-Beispiel und im GCHandle-Beispiel.

Das Callback-Beispiel verwendet die folgenden nicht verwalteten Funktionen, die jeweils zusammen mit ihrer ursprünglichen Funktionsdeklaration aufgeführt werden:

  • TestCallBack aus PinvokeLib.dll exportiert.

    void TestCallBack(FPTR pf, int value);
    
  • TestCallBack2 aus PinvokeLib.dll exportiert.

    void TestCallBack2(FPTR2 pf2, char* value);
    

PinvokeLib.dll ist eine benutzerdefinierte, nicht verwaltete Bibliothek, die eine Implementierung für die zuvor aufgelisteten Funktionen enthält.

In diesem Beispiel enthält die LibWrap-Klasse verwaltete Prototypen für die Methoden TestCallBack und TestCallBack2. Beide Methoden übergeben einen Delegaten an eine Rückruffunktion als Parameter. Die Signatur des Delegaten muss mit der Signatur der Methode übereinstimmen, auf die er verweist. So besitzen die Delegaten FPtr und FPtr2 beispielsweise Signaturen, die mit den Methoden DoSomething und DoSomething2 identisch sind.

Deklarieren von Prototypen


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

Aufrufen von Funktionen

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

Siehe auch

Konzepte

Verschiedene Marshallingbeispiele

Datentypen für den Plattformaufruf

Erstellen von Prototypen in verwaltetem Code