从数据来自C / C ++结构的byte []数组填充C#结构的最佳方法是什么?C结构看起来像这样(我的C非常生锈):
typedef OldStuff { CHAR Name[8]; UInt32 User; CHAR Location[8]; UInt32 TimeStamp; UInt32 Sequence; CHAR Tracking[16]; CHAR Filler[12]; }
并会填充如下内容:
[StructLayout(LayoutKind.Explicit, Size = 56, Pack = 1)] public struct NewStuff { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] [FieldOffset(0)] public string Name; [MarshalAs(UnmanagedType.U4)] [FieldOffset(8)] public uint User; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] [FieldOffset(12)] public string Location; [MarshalAs(UnmanagedType.U4)] [FieldOffset(20)] public uint TimeStamp; [MarshalAs(UnmanagedType.U4)] [FieldOffset(24)] public uint Sequence; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] [FieldOffset(28)] public string Tracking; }
什么是复制最好的办法OldStuff来NewStuff,如果OldStuff为byte []数组获得通过?
OldStuff
NewStuff
我目前正在执行以下操作,但感觉有些笨拙。
GCHandle handle; NewStuff MyStuff; int BufferSize = Marshal.SizeOf(typeof(NewStuff)); byte[] buff = new byte[BufferSize]; Array.Copy(SomeByteArray, 0, buff, 0, BufferSize); handle = GCHandle.Alloc(buff, GCHandleType.Pinned); MyStuff = (NewStuff)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NewStuff)); handle.Free();
有更好的方法来做到这一点吗?
使用BinaryReader该类是否会比固定内存和使用提供任何性能提升Marshal.PtrStructure?
BinaryReader
Marshal.PtrStructure
从这种情况下我可以看到,您不需要复制SomeByteArray到缓冲区中。您只需要从中获取句柄SomeByteArray,将其固定,IntPtr使用复制数据PtrToStructure,然后释放即可。无需副本。
SomeByteArray
IntPtr
PtrToStructure
那将是:
NewStuff ByteArrayToNewStuff(byte[] bytes) { GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); try { NewStuff stuff = (NewStuff)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NewStuff)); } finally { handle.Free(); } return stuff; }
通用版本:
T ByteArrayToStructure<T>(byte[] bytes) where T: struct { T stuff; GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); try { stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); } finally { handle.Free(); } return stuff; }
更简单的版本(需要unsafe切换):
unsafe
unsafe T ByteArrayToStructure<T>(byte[] bytes) where T : struct { fixed (byte* ptr = &bytes[0]) { return (T)Marshal.PtrToStructure((IntPtr)ptr, typeof(T)); } }