53

マネージ コードから WinApi 関数にオブジェクトを として渡したいと考えていますIntPtr。このオブジェクトは、マネージ コードのコールバック関数に として渡されIntPtrます。これは構造体ではなく、クラスのインスタンスです。

objectに変換しIntPtrたり元に戻したりするにはどうすればよいですか?

4

2 に答える 2

60

したがって、WinApi を介してコールバック関数にリストを渡したい場合は、GCHandleを使用します。

// object to IntPtr (before calling WinApi):
List<string> list1 = new List<string>();
GCHandle handle1 = GCHandle.Alloc(list1);
IntPtr parameter = (IntPtr) handle1;
// call WinAPi and pass the parameter here
// then free the handle when not needed:
handle1.Free();

// back to object (in callback function):
GCHandle handle2 = (GCHandle) parameter;
List<string> list2 = (handle2.Target as List<string>);
list2.Add("hello world");

デビッド・ヘファーナンへのThx

編集:コメントに記載されているように、使用後にハンドルを解放する必要があります。また、キャストを使用しました。こちらのように静的メソッドGCHandle.ToIntPtr(handle1)を使用するのが賢明かもしれません。私はそれを確認していません。GCHandle.FromIntPtr(parameter)

于 2013-06-27T10:12:37.910 に答える
13

受け入れられた答えは正しいですが、少し追加したかったのです。

このための拡張機能を作成するのが好きになったので、次のように表示されますlist1.ToIntPtr()

public static class ObjectHandleExtensions
{
    public static IntPtr ToIntPtr(this object target)
    {
        return GCHandle.Alloc(target).ToIntPtr();
    }

    public static GCHandle ToGcHandle(this object target)
    {
        return GCHandle.Alloc(target);
    }

    public static IntPtr ToIntPtr(this GCHandle target)
    {
        return GCHandle.ToIntPtr(target);
    }
}

また、これをどの程度行っているかによっては、リストをIDisposable.

public class GCHandleProvider : IDisposable
{
    public GCHandleProvider(object target)
    {
        Handle = target.ToGcHandle();
    }

    public IntPtr Pointer => Handle.ToIntPtr();

    public GCHandle Handle { get; }

    private void ReleaseUnmanagedResources()
    {
        if (Handle.IsAllocated) Handle.Free();
    }

    public void Dispose()
    {
        ReleaseUnmanagedResources();
        GC.SuppressFinalize(this);
    }

    ~GCHandleProvider()
    {
        ReleaseUnmanagedResources();
    }
}

そして、あなたはそれを次のように消費するかもしれません:

using (var handleProvider = new GCHandleProvider(myList))
{
    var b = EnumChildWindows(hwndParent, CallBack, handleProvider.Pointer);
}
于 2018-08-30T19:18:29.553 に答える