C# - How To Convert Object To IntPtr And Back?

六眼飞鱼酱① 提交于 2019-11-26 13:09:18

问题


I want to pass an object from managed code to a WinApi function as IntPtr. It will pass this object back to my callback function in managed code as IntPtr. It\'s not a structure, it\'s an instance of a class.

How do I convert object to IntPtr and back ?


回答1:


So if I want to pass a list to my callback function through WinApi I use 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 to David Heffernan

Edit: As noted in the comments, you need to free the handle after use. Also I used casting. It might be wise to use the static methods GCHandle.ToIntPtr(handle1) and GCHandle.FromIntPtr(parameter) like here. I haven't verified that.




回答2:


While the accepted answer is correct, I wanted to add a little bit to it.

I have grown fond of creating extensions for this so it reads: 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);
    }
}

Also, depending on how much of this you're doing, it might be nice to contain your list in an 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();
    }
}

And then you might consume it like this:

using (var handleProvider = new GCHandleProvider(myList))
{
    var b = EnumChildWindows(hwndParent, CallBack, handleProvider.Pointer);
}


来源:https://stackoverflow.com/questions/17339928/c-sharp-how-to-convert-object-to-intptr-and-back

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!