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 Microsoft .NET Framework SDK includes the complete Visual Basic .NET and C# versions of this sample in Samples\Technologies\Interop\Platform-Invoke.
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.
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
[C#]
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
[C#]
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;
}
}
See Also
Miscellaneous Marshaling Samples | Platform Invoke Data Types | Creating Prototypes in Managed Code