GCHandle, exemple
Cet exemple montre comment passer un objet managé à une fonction non managée qui attend un type LPARAM. Un type LPARAM est un pointeur vers un paramètre non managé.
L'exemple GCHandle utilise la fonction non managée suivante, illustrée avec sa déclaration de fonction d'origine :
EnumWindows exportée à partir de User32.dll.
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);
Dans cet exemple, la classe LibWrap contient un prototype managé de la méthode EnumWindows. La méthode managée remplace le délégué CallBack par le pointeur fonction WNDENUMPROC et un pointeur IntPtr par le type LPARAM en tant que paramètres.
La classe App crée un handle vers l'objet managé à l'aide de la méthode GCHandle.Alloc, évitant ainsi que l'objet managé soit collecté. Un appel à la méthode EnumWindows passe le délégué et l'objet managé, en effectuant un cast du handle vers un IntPtr. La fonction non managée repasse le type à l'appelant sous la forme d'un paramètre de la fonction de rappel.
Déclaration de 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
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);
};
Fonctions d'appel
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;
}
};