使用Microsoft.Win32.SafeHandles与Marshal.AllocHGlobal和Marshal.FreeHGlobal

Kei*_*ith 2 .net winapi marshalling

我有一个.Net类,为struct使用分配非托管内存Marshal.AllocHGlobal,然后使用它来处理它Marshal.FreeHGlobal.

我理解这些类Microsoft.Win32.SafeHandles提供了处理这个的包装器,但是不清楚如何实例化它们(很多都没有构造函数) - 我应该编写抽象基类的特定实现还是有一些方法来使用它们在extern声明中?

xan*_*tos 6

子类化的主要问题SafeHandleMarshal.DestroyStructure你需要Type结构...这使得一切都更复杂.

你不能使用泛型(因为它们与pinvoke不兼容)...所以你可以有多SafeHandle个子类(每个子类一个Type),或者SafeHandle你手动设置的结构类型中的属性......或者你可以使SafeHandle接受结构的构造函数被封送并在Type内部设置一个属性.

我正在使用最后两个"选项"(Type可以手动设置或可以由构造函数自动设置的属性)

示例MySafeHandle:

public class MySafeHandle : SafeHandle
{
    public Type Type { get; set; }

    public MySafeHandle() : base(IntPtr.Zero, true)
    {
    }

    public MySafeHandle(object obj)
        : base(IntPtr.Zero, true)
    {
        if (obj != null)
        {
            Type = obj.GetType();
            int size = Marshal.SizeOf(obj);

            try
            {
            }
            finally
            {
                // the finally part can't be interrupted by
                // Thread.Abort
                handle = Marshal.AllocHGlobal(size);
                Marshal.StructureToPtr(obj, handle, false);
            }
        }
    }

    public override bool IsInvalid
    {
        get { return handle == IntPtr.Zero; }
    }

    [SecurityCritical]
    protected override bool ReleaseHandle()
    {
        if (handle != IntPtr.Zero)
        {
            if (Type == null)
            {
                throw new InvalidOperationException();
            }

            try
            {
            }
            finally
            {
                Marshal.DestroyStructure(handle, Type);
                Marshal.FreeHGlobal(handle);
                handle = IntPtr.Zero;
            }

            return true;
        }

        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

你应该使用的构造函数是用结构编组的构造函数Marshal.StructureToPtr.它的优点是它可以保存结构的类型,以便以后可以使用它Marshal.DestroyStructure.

  • 我现在已经测试了 - 我可以使用`SafeHandle`作为`extern`调用的参数(而不是用于分配的`IntPtr`),但是传递通用的`SafeStructHandle <T>`来隐式转换. (2认同)