Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом примере показано, как передать делегаты в неуправляемую функцию, ожидающую указателей функции. Делегат — это класс, который может содержать ссылку на метод и эквивалентен типа-безопасному указателю функции или функции обратного вызова.
Замечание
При использовании делегата внутри вызова среда CLR защищает делегата от сборки мусора в течение этого вызова. Однако, если неуправляемая функция сохраняет делегат для использования после завершения вызова, то необходимо вручную предотвратить сборку мусора до тех пор, пока неуправляемая функция полностью не завершит свою работу с делегатом. Дополнительные сведения см. в примере HandleRef и GCHandle.
В примере обратного вызова используются следующие неуправляемые функции, показанные с их исходным объявлением функции:
TestCallBack
экспортируется из PinvokeLib.dll.void TestCallBack(FPTR pf, int value);
TestCallBack2
экспортируется из PinvokeLib.dll.void TestCallBack2(FPTR2 pf2, char* value);
PinvokeLib.dll — это пользовательская неуправляемая библиотека, содержащая реализацию для ранее перечисленных функций.
В этом примере NativeMethods
класс содержит управляемые прототипы для TestCallBack
методов и TestCallBack2
методов. Оба метода передают делегат в функцию обратного вызова в качестве параметра. Подпись делегата должна соответствовать сигнатуре метода, на который он ссылается. Например, у делегатов FPtr
и FPtr2
сигнатуры идентичны методам DoSomething
и DoSomething2
.
Объявление прототипов
public delegate bool FPtr(int value);
public delegate bool FPtr2(String^ value);
private ref class NativeMethods
{
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);
internal static class NativeMethods
{
// Declares managed prototypes for unmanaged functions.
[DllImport("..\\LIB\\PinvokeLib.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void TestCallBack(FPtr cb, int value);
[DllImport("..\\LIB\\PinvokeLib.dll", CallingConvention = CallingConvention.Cdecl)]
internal 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
Friend Class NativeMethods
' Declares managed prototypes for unmanaged functions.
<DllImport("..\LIB\PinvokeLib.dll", CallingConvention:=CallingConvention.Cdecl)>
Friend Shared Sub TestCallBack(
ByVal cb As FPtr, ByVal value As Integer)
End Sub
<DllImport("..\LIB\PinvokeLib.dll", CallingConvention:=CallingConvention.Cdecl)>
Friend Shared Sub TestCallBack2(
ByVal cb2 As FPtr2, ByVal value As String)
End Sub
End Class
Вызов функций
public ref class App
{
public:
static void Main()
{
FPtr^ cb = gcnew FPtr(&App::DoSomething);
NativeMethods::TestCallBack(cb, 99);
FPtr2^ cb2 = gcnew FPtr2(&App::DoSomething2);
NativeMethods::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);
NativeMethods.TestCallBack(cb, 99);
FPtr2 cb2 = new FPtr2(App.DoSomething2);
NativeMethods.TestCallBack2(cb2, "abc");
}
public static bool DoSomething(int value)
{
Console.WriteLine($"\nCallback called with param: {value}");
// ...
return true;
}
public static bool DoSomething2(string value)
{
Console.WriteLine($"\nCallback called with param: {value}");
// ...
return true;
}
}
Public Class App
Public Shared Sub Main()
Dim cb As FPtr = AddressOf App.DoSomething
Dim cb2 As FPtr2 = AddressOf App.DoSomething2
NativeMethods.TestCallBack(cb, 99)
NativeMethods.TestCallBack2(cb2, "abc")
End Sub
Public Shared Function DoSomething(ByVal value As Integer) As Boolean
Console.WriteLine(ControlChars.CrLf + $"Callback called with param: {value}")
' ...
Return True
End Function
Public Shared Function DoSomething2(ByVal value As String) As Boolean
Console.WriteLine(ControlChars.CrLf + $"Callback called with param: {value}")
' ...
Return True
End Function
End Class