GCHandle Sample
This sample demonstrates how to pass a managed object to an unmanaged function that expects an LPARAM type. An LPARAM type is a pointer to an unmanaged parameter.
The GCHandle sample uses the following unmanaged function, shown with its original function declaration:
EnumWindows exported from User32.dll.
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);
In this sample, the LibWrap class contains a managed prototype of the EnumWindows method. As its parameters, the managed method substitutes the CallBack delegate for the WNDENUMPROC function pointer and an IntPtr pointer for the LPARAM type.
The App class creates a handle to the managed object using the GCHandle.Alloc method, which prevents the managed object from being collected. A call to the EnumWindows method passes the delegate and the managed object, casting the handle to an IntPtr. The unmanaged function passes the type back to the caller as a parameter of the callback function.
The source code for the following code examples is provided by the .NET Framework Platform Invoke Technology Sample.
Declaring Prototypes
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 );
}
Calling Functions
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;
}
}