Пример GCHandle
В этом примере показан способ передачи управляемого объекта в неуправляемую функцию, ожидающую тип LPARAM. Тип LPARAM является указателем на неуправляемый параметр.
В примере GCHandle используются следующие неуправляемые функции, показанные со своим исходным объявлением.
Функция EnumWindows, экспортированная из User32.dll.
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);
В этом примере класс LibWrap содержит управляемый прототип метода EnumWindows. В качестве параметров управляемый метод заменяет указатель на функцию WNDENUMPROC на делегат CallBack, а тип LPARAM на указатель IntPtr.
Класс App создает дескриптор для управляемого объекта, используя метод GCHandle.Alloc, предотвращающий сборку управляемого объекта. Вызов метода EnumWindows передает делегат и управляемый объект, выполняя приведение дескриптора к типу IntPtr. Неуправляемая функция передает тип обратно вызывающему объекту, в качестве параметра функции обратного вызова.
Объявление прототипов
Public Delegate Function CallBack(ByVal handle As Integer, _
ByVal param As IntPtr) As Boolean
Public Class LibWrap
' Passes a managed object instead of an LPARAM.
' Declares a managed prototype for the unmanaged function.
Declare Function EnumWindows Lib "user32.dll" ( _
ByVal cb As CallBack, ByVal param As IntPtr) As Boolean
End Class
public delegate bool CallBack(int handle, IntPtr param);
public class LibWrap
{
// Passes a managed object as an LPARAM type.
// Declares a managed prototype for the unmanaged function.
[DllImport("user32.dll")]
public static extern bool EnumWindows(CallBack cb, IntPtr param);
}
public delegate bool CallBack(int handle, IntPtr param);
public ref class LibWrap
{
public:
// Passes a managed object as an LPARAM type.
// Declares a managed prototype for the unmanaged function.
[DllImport("user32.dll")]
static bool EnumWindows(CallBack^ cb, IntPtr param);
};
Вызов функций
Public Class App
Public Shared Sub Main()
Dim tw As TextWriter = System.Console.Out
Dim gch As GCHandle = GCHandle.Alloc(tw)
' Platform invoke prevents the delegate from being garbage collected
' before the call ends.
Dim cewp As CallBack
cewp = AddressOf App.CaptureEnumWindowsProc
LibWrap.EnumWindows(cewp, GCHandle.op_Explicit(gch))
gch.Free()
End Sub
Public Shared Function CaptureEnumWindowsProc(ByVal handle As Integer, _
ByVal param As IntPtr) As Boolean
Dim gch As GCHandle = GCHandle.op_Explicit(param)
Dim tw As TextWriter = CType(gch.Target, TextWriter)
tw.WriteLine(handle)
Return True
End Function
End Class
public class App
{
public static void Main()
{
TextWriter tw = System.Console.Out;
GCHandle gch = GCHandle.Alloc(tw);
CallBack cewp = new CallBack(CaptureEnumWindowsProc);
// Platform invoke prevents the delegate from being garbage
// collected before the call ends.
LibWrap.EnumWindows(cewp, (IntPtr)gch);
gch.Free();
}
private static bool CaptureEnumWindowsProc(int handle, IntPtr param)
{
GCHandle gch = (GCHandle)param;
TextWriter tw = (TextWriter)gch.Target;
tw.WriteLine(handle);
return true;
}
}
public ref class App
{
public:
static void Main()
{
TextWriter^ tw = System::Console::Out;
GCHandle gch = GCHandle::Alloc(tw);
CallBack^ cewp = gcnew CallBack(&CaptureEnumWindowsProc);
// Platform invoke prevents the delegate from being garbage
// collected before the call ends.
LibWrap::EnumWindows(cewp, (IntPtr)gch);
gch.Free();
}
private:
static bool CaptureEnumWindowsProc(int handle, IntPtr param)
{
GCHandle gch = (GCHandle)param;
TextWriter^ tw = (TextWriter^)gch.Target;
tw->WriteLine(handle);
return true;
}
};