GCHandle のサンプル

このサンプルでは、LPARAM 型を要求するアンマネージ関数にマネージ オブジェクトを渡す方法を示します。 LPARAM 型とは、アンマネージ パラメーターへのポインターのことです。

GCHandle のサンプルで使用するアンマネージ関数とその関数宣言を次に示します。

  • User32.dll からエクスポートされる EnumWindows

    BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);
    

このサンプルでは、LibWrap クラスには EnumWindows メソッドのマネージ プロトタイプが含まれます。 マネージ メソッドでは、パラメーターとして WNDENUMPROC 関数の代わりに CallBack デリゲートが使用され、LPARAM 型の代わりに IntPtr ポインターが使用されます。

App クラスは、マネージ オブジェクトがコレクトされるのを防ぐ GCHandle.Alloc メソッドを使用して、マネージ オブジェクトを識別するハンドルを作成します。 EnumWindows メソッドを呼び出すと、デリゲートとマネージ オブジェクトが渡され、IntPtr を識別するハンドルがキャストされます。 このアンマネージ関数は、コールバック関数のパラメーターとして型を呼び出し元に戻します。

プロトタイプの宣言

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);
};

関数の呼び出し

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;
    }
};

参照

概念

各種のマーシャリングのサンプル

プラットフォーム呼び出しのデータ型

マネージ コードでのプロトタイプの作成