回呼範例

這個範例示範如何將委派傳遞至預期函式指標的 Unmanaged 函式。 委派是一種含有方法參考的類別,相當於型別安全函式指標或回呼函式 (Callback Function)。

注意事項注意事項

當您在呼叫內使用委派時,在該呼叫期間,Common Language Runtime 會保護委派不被記憶體回收。不過,如果 Unmanaged 函式儲存在呼叫完成之後所要使用的委派,您必須在 Unmanaged 函式完成委派之前手動防止記憶體回收。如需詳細資訊,請參閱 HandleRef 範例GCHandle 範例

回呼範例使用下列 Unmanaged 函式,顯示其原始函式宣告:

  • 從 PinvokeLib.dll 匯出 TestCallBack

    void TestCallBack(FPTR pf, int value);
    
  • 從 PinvokeLib.dll 匯出 TestCallBack2

    void TestCallBack2(FPTR2 pf2, char* value);
    

PinvokeLib.dll 是自訂的 Unmanaged 程式庫,包含先前列示之函式的實作。

在這個範例中,LibWrap 類別包含 TestCallBack 和 TestCallBack2 方法的 Managed 原型。 這兩個方法會將委派當成參數傳遞至回呼函式。 委派的簽章 (Signature) 必須符合它所參考的方法簽章。 例如,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;
    }
};

請參閱

概念

其他封送處理範例

平台叫用資料型別

在 Managed 程式碼中建立原型