Esempio di GCHandle

In questo esempio viene illustrato come passare un oggetto gestito a una funzione non gestita per la quale è previsto un tipo LPARAM. Il tipo LPARAM è un puntatore a un parametro non gestito.

Nell'esempio di GCHandle viene utilizzata la seguente funzione non gestita, illustrata con la dichiarazione di funzione originale:

  • EnumWindows esportata da User32.dll.

    BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);
    

In questo esempio la classe LibWrap contiene un prototipo gestito del metodo EnumWindows. Come parametri, nel metodo gestito vengono sostituiti il delegato CallBack per il puntatore a funzione WNDENUMPROC e un puntatore IntPtr per il tipo LPARAM.

La classe App crea un handle all'oggetto gestito mediante il metodo GCHandle.Alloc, che evita l'operazione di Garbage Collection sull'oggetto gestito. Con una chiamata al metodo EnumWindows il delegato e l'oggetto gestito vengono passati e viene effettuato il cast dell'handle su un puntatore IntPtr. La funzione non gestita restituisce il tipo al chiamante come parametro della funzione di callback.

Il codice sorgente per gli esempi di codice riportati di seguito è fornito dall'Esempio di tecnologia di richiamo piattaforma di .NET Framework.

Dichiarazione dei prototipi

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

Chiamata delle funzioni

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

Vedere anche

Concetti

Esempi vari di marshalling
Tipi di dati del richiamo piattaforma
Creazione di prototipi nel codice gestito