2

有没有办法将结构(可能存储在TypedReference中)编组到非托管内存而不实际装箱?结构的类型在运行时是未知的,所以我不能使用 StructureToPtr (.NET 4.5.1) 的泛型重载。我可以获得StructureToPtr重载的 MethodInfo ,但似乎没有一种方法可以通过泛型引用或TypedReference来调用它。

编辑:通用的StructureToPtr仍然将结构装箱,因此尝试调用它是无用的。

4

1 回答 1

2

我终于找到了答案,SafeBuffer班级。它包含了我想要的——结构和使用TypedReference通用参数的编组方法。所以,制作一个包装器真的很简单:

public static unsafe class InteropTools
{
    private static readonly Type SafeBufferType = typeof(SafeBuffer);
    public delegate void PtrToStructureNativeDelegate(byte* ptr, TypedReference structure, uint sizeofT);
    public delegate void StructureToPtrNativeDelegate(TypedReference structure, byte* ptr, uint sizeofT);
    const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Static;
    private static readonly MethodInfo PtrToStructureNativeMethod = SafeBufferType.GetMethod("PtrToStructureNative", flags);
    private static readonly MethodInfo StructureToPtrNativeMethod = SafeBufferType.GetMethod("StructureToPtrNative", flags);
    public static readonly PtrToStructureNativeDelegate PtrToStructureNative = (PtrToStructureNativeDelegate)Delegate.CreateDelegate(typeof(PtrToStructureNativeDelegate), PtrToStructureNativeMethod);
    public static readonly StructureToPtrNativeDelegate StructureToPtrNative = (StructureToPtrNativeDelegate)Delegate.CreateDelegate(typeof(StructureToPtrNativeDelegate), StructureToPtrNativeMethod);

    private static readonly Func<Type,bool,int> SizeOfHelper_f = (Func<Type,bool,int>)Delegate.CreateDelegate(typeof(Func<Type,bool,int>), typeof(Marshal).GetMethod("SizeOfHelper", flags));

    public static void StructureToPtrDirect(TypedReference structure, IntPtr ptr, int size)
    {
        StructureToPtrNative(structure, (byte*)ptr, unchecked((uint)size));
    }

    public static void StructureToPtrDirect(TypedReference structure, IntPtr ptr)
    {
        StructureToPtrDirect(structure, ptr, SizeOf(__reftype(structure)));
    }

    public static void PtrToStructureDirect(IntPtr ptr, TypedReference structure, int size)
    {
        PtrToStructureNative((byte*)ptr, structure, unchecked((uint)size));
    }

    public static void PtrToStructureDirect(IntPtr ptr, TypedReference structure)
    {
        PtrToStructureDirect(ptr, structure, SizeOf(__reftype(structure)));
    }

    public static void StructureToPtr<T>(ref T structure, IntPtr ptr)
    {
        StructureToPtrDirect(__makeref(structure), ptr);
    }

    public static void PtrToStructure<T>(IntPtr ptr, out T structure)
    {
        structure = default(T);
        PtrToStructureDirect(ptr, __makeref(structure));
    }

    public static T PtrToStructure<T>(IntPtr ptr)
    {
        T obj;
        PtrToStructure(ptr, out obj);
        return obj;
    }

    public static int SizeOf<T>(T structure)
    {
        return SizeOf<T>();
    }

    public static int SizeOf<T>()
    {
        return SizeOf(typeof(T));
    }

    public static int SizeOf(Type t)
    {
        return SizeOfHelper_f(t, true);
    }
}

用法

Guid g = Guid.NewGuid();
int size = InteropTools.SizeOf(g);
IntPtr mem = Marshal.AllocHGlobal(size);
InteropTools.StructureToPtr(ref g, mem);

Guid g2 = InteropTools.PtrToStructure<Guid>(mem);

现在,与类中的非泛型对象获取方法相比,它实际上有什么优势Marshal吗?似乎减少了StructureToPtr大约 80% 的时间,并且PtrToStructure可以减少几乎 95% 的时间。此外,这些方法可以正确处理可为空的类型。

于 2014-11-14T13:18:42.883 回答