我想将托管代码中的对象作为IntPtr
传递给WinApi函数。它会将此对象作为IntPtr
传递回托管代码中的回调函数。它不是一个结构,而是一个类的实例。
如何将object
转换为IntPtr
并返回?
答案 0 :(得分:52)
因此,如果我想通过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 to David Heffernan
编辑:如评论中所述,您需要在使用后释放句柄。我也用过铸造。使用静态方法GCHandle.ToIntPtr(handle1)
和GCHandle.FromIntPtr(parameter)
(如here)可能是明智之举。我还没有证实。
答案 1 :(得分:5)
虽然接受的答案是正确的,但我想在此添加一些内容。
我已经很喜欢为此创建扩展名,因此其内容为:$(function(){
$('#stack_name').on('change keyup paste', function(){
$(#'stack_label').text($(this).val());
});
$('#bucket').change(function(){
$(#'bucket_label').text($(this).val());
});
$('#key_pair').change(function(){
$(#'key_pair_label').text($(this).val());
});
});
。
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();
}
}