Condividi tramite


Esempio di callback

In questo esempio viene dimostrato come passare i delegati a una funzione non gestita per la quale sono previsti puntatori a funzione. Un delegato è una classe che può contenere un riferimento a un metodo ed è equivalente a un puntatore a funzione indipendente dai tipi o a una funzione callback.

NotaNota

Quando si utilizza un delegato in una chiamata, Common Language Runtime consente di proteggerlo dalla procedura di Garbage Collection per la durata di tale chiamata.Se tuttavia il delegato viene memorizzato dalla funzione non gestita per essere utilizzato al termine della chiamata, è necessario evitare manualmente l'operazione di Garbage Collection finché la funzione non gestita non termina l'uso del delegato.Per ulteriori informazioni, vedere Esempio di HandleRef ed Esempio di GCHandle.

Nell'esempio di callback vengono utilizzate le seguenti funzioni non gestite, illustrate con la dichiarazione di funzione originale:

  • TestCallBack esportata da PinvokeLib.dll.

    void TestCallBack(FPTR pf, int value);
    
  • TestCallBack2 esportata da PinvokeLib.dll.

    void TestCallBack2(FPTR2 pf2, char* value);
    

PinvokeLib.dll è una libreria non gestita personalizzata contenente un'implementazione per le funzioni elencate in precedenza.

In questo esempio, la classe LibWrap contiene i prototipi gestiti per i metodi TestCallBack e TestCallBack2. Entrambi i metodi passano un delegato a una funzione di callback come parametro. La firma del delegato deve corrispondere a quella del metodo a cui fa riferimento. I delegati FPtr e FPtr2 ad esempio hanno firme identiche ai metodi DoSomething e DoSomething2.

Dichiarazione dei prototipi


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

Chiamata delle funzioni

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

Vedere anche

Concetti

Esempi vari di marshalling

Tipi di dati di platform invoke

Creazione di prototipi nel codice gestito