有没有一种方法来编组结构(可能存储在TypedReference)非托管内存没有实际装箱呢?结构的类型在运行时是未知的,所以我不能使用StructureToPtr(.NET 4.5.1)的通用重载。我可以得到一个MethodInfo的StructureToPtr重载,但似乎没有办法调用它通过通用引用或TypedReference。Marshal.StructureToPtr没有装箱
编辑:通用StructureToPtr仍然结构的结构,所以试图调用它是没有用的。
有没有一种方法来编组结构(可能存储在TypedReference)非托管内存没有实际装箱呢?结构的类型在运行时是未知的,所以我不能使用StructureToPtr(.NET 4.5.1)的通用重载。我可以得到一个MethodInfo的StructureToPtr重载,但似乎没有办法调用它通过通用引用或TypedReference。Marshal.StructureToPtr没有装箱
编辑:通用StructureToPtr仍然结构的结构,所以试图调用它是没有用的。
我终于找到了答案,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%的时间。此外,这些方法可以正确处理可空类型。
你测试过x86和x64吗?在不安之间,拳击的表现特征会有所不同(如果你想包括这个,RyuJIT也是如此)。尽管我认为这确实没什么关系 - 如果编组是你想要完全消除的瓶颈(或者通过复制批量而不是单个值来减少开销)。 –
@JeroenMostert不,但似乎我得到的结果是错误的。尽管在Release中运行,但所连接的调试器似乎仍然会影响性能。 – IllidanS4
是的 - 事实上,Debug与Release通常对性能没有可衡量的影响,因为编译器对生成的IL进行的优化量实际上相当有限(它倾向于让抖动完成繁重的工作)。然而,在调试器下运行,完全使任何性能测试无效。 –
为什么你需要'StructureToPtr'的通用版本?编辑:即使通用版本只会调用非通用版本并导致一个框。 – leppie
@leppie哦,我认为通用的一些做一些技巧,以避免拳击。它有什么目的,除了混淆? – IllidanS4
也许有特殊处理,但没有我在文档中看到......不知道目的是什么...... – leppie