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


Пример GCHandle

Обновлен: Ноябрь 2007

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

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

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

    BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);
    

В этом примере класс LibWrap содержит управляемый прототип метода EnumWindows. В качестве параметров управляемый метод заменяет указатель на функцию WNDENUMPROC на делегат CallBack, а тип LPARAM на указатель IntPtr.

Класс App создает дескриптор для управляемого объекта, используя метод GCHandle.Alloc, предотвращающий сборку управляемого объекта. Вызов метода EnumWindows передает делегат и управляемый объект, выполняя приведение дескриптора к типу IntPtr. Неуправляемая функция передает тип обратно вызывающему объекту в качестве параметра функции обратного вызова.

Исходный код для следующих примеров кода см. в разделе Пример технологии вызова неуправляемого кода для .NET Framework.

Объявление прототипов

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 'LibWrap
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 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 'Main
   
   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 'CaptureEnumWindowsProc
End Class 'App 
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;
   }   
}

См. также

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

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

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

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