Поделиться через


Пример Callback

В этом примере показан способ передачи делегатов в неуправляемую функцию, ожидающую указатели функции. Делегат является классом, который может содержать ссылку на метод и эквивалентен типобезопасному указателю функции или функции обратного вызова.

ПримечаниеПримечание

При использовании делегата в вызове, среда CLR защищает делегат от процесса сбора мусора на протяжении всего вызова.Но если неуправляемая функция сохраняет делегат для использования после завершения вызова, необходимо предотвратить сборку мусора вручную до тех пор, пока неуправляемая функция не закончит работу с делегатом.Дополнительные сведения см. в разделах Пример HandleRef и Пример GCHandle.

В примере Callback используются следующие неуправляемые функции, показанные со своим исходным объявлением.

  • Функция TestCallBack, экспортированная из PinvokeLib.dll.

    void TestCallBack(FPTR pf, int value);
    
  • TestCallBack2, экспортированная из PinvokeLib.dll.

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

См. также

Основные понятия

Другие примеры маршалинга

Типы данных вызовов неуправляемого кода

Создание прототипов в управляемом коде