没有拳击的Marshal.StructureToPtr

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

编辑:通用的StructureToPtr仍然对结构进行封装,因此尝试调用它是没用的。

我终于找到了答案,即SafeBuffer类。 它包含我想要的结果 – 使用TypedReference和generics参数的编组方法结构。 那么,制作包装器真的很简单:

 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 SizeOfHelper_f = (Func)Delegate.CreateDelegate(typeof(Func), 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(ref T structure, IntPtr ptr) { StructureToPtrDirect(__makeref(structure), ptr); } public static void PtrToStructure(IntPtr ptr, out T structure) { structure = default(T); PtrToStructureDirect(ptr, __makeref(structure)); } public static T PtrToStructure(IntPtr ptr) { T obj; PtrToStructure(ptr, out obj); return obj; } public static int SizeOf(T structure) { return SizeOf(); } public static int SizeOf() { 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(mem); 

现在,它实际上是否比Marshal类中的非generics对象捕获方法有任何优势? 看起来StructureToPtr时间减少了约80%,而PtrToStructure时间缩短了近95%。 此外,这些方法可以正确处理可空类型。