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


Пример 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;
    }
};

См. также

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

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

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

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