Ejemplo GCHandle
En este ejemplo se demuestra cómo pasar un objeto administrado a una función no administrada que espera recibir un tipo LPARAM. Un tipo LPARAM es un puntero a un parámetro no administrado.
En el ejemplo GCHandle se utiliza la siguiente función no administrada, que se muestra con su declaración de función original:
EnumWindows exportada desde User32.dll.
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);
En este ejemplo, la clase LibWrap contiene un prototipo administrado del método EnumWindows. Como parámetros, el método administrado sustituye el puntero a función WNDENUMPROC por el delegado CallBack y el tipo LPARAM por un puntero IntPtr.
La clase App crea un identificador para el objeto administrado mediante el método GCHandle.Alloc, que impide la recolección de elementos no utilizados en el objeto administrado. En una llamada al método EnumWindows se pasa el delegado y el objeto administrado, con lo que el identificador se convierte en IntPtr. La función no administrada vuelve a pasar el tipo al llamador como parámetro de la función de devolución de llamada.
Declaración de prototipos
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);
};
Llamadas a funciones
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;
}
};
Vea también
Conceptos
Diversos ejemplos de cálculo de referencias