マネージ コードから WinApi 関数にオブジェクトを として渡したいと考えていますIntPtr
。このオブジェクトは、マネージ コードのコールバック関数に として渡されIntPtr
ます。これは構造体ではなく、クラスのインスタンスです。
object
に変換しIntPtr
たり元に戻したりするにはどうすればよいですか?
マネージ コードから WinApi 関数にオブジェクトを として渡したいと考えていますIntPtr
。このオブジェクトは、マネージ コードのコールバック関数に として渡されIntPtr
ます。これは構造体ではなく、クラスのインスタンスです。
object
に変換しIntPtr
たり元に戻したりするにはどうすればよいですか?
したがって、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)
受け入れられた答えは正しいですが、少し追加したかったのです。
このための拡張機能を作成するのが好きになったので、次のように表示されます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);
}