GCHandle 示例
更新:2007 年 11 月
该示例说明如何将托管对象传递给需要 LPARAM 类型的非托管函数。LPARAM 类型是指向非托管参数的指针。
GCHandle 示例使用以下非托管函数(这里同时显示其原始函数声明):
从 User32.dll 导出的 EnumWindows。
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);
在该示例中,LibWrap 类包含 EnumWindows 方法的托管原型。作为其参数,该托管方法用 CallBack 委托替换 WNDENUMPROC 函数指针,并用 IntPtr 指针替换 LPARAM 类型。
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;
}
}