此任務涉及將包含來自C/C 結構體資料的位元組數組轉換為對應的C#結構體。 C/C 結構體如下圖所示:
<code class="language-c++">typedef struct OldStuff { CHAR Name[8]; UInt32 User; CHAR Location[8]; UInt32 TimeStamp; UInt32 Sequence; CHAR Tracking[16]; CHAR Filler[12]; } OldStuff;</code>
而C#結構體,名為NewStuff
,定義如下:
<code class="language-csharp">[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; }</code>
最初,考慮了一種比較繁瑣的方法,涉及固定記憶體並使用Marshal.PtrToStructure
:
<code class="language-csharp">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();</code>
經過進一步分析,確定原始方法中的緩衝區複製是不必要的。相反,直接的句柄固定就夠了:
<code class="language-csharp">GCHandle handle; NewStuff MyStuff; handle = GCHandle.Alloc(SomeByteArray, GCHandleType.Pinned); try { MyStuff = (NewStuff)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NewStuff)); } finally { handle.Free(); }</code>
此外,可以使用泛型甚至更簡單的版本(需要不安全切換):
<code class="language-csharp">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; }</code>
<code class="language-csharp">unsafe T ByteArrayToStructure<T>(byte[] bytes) where T : struct { fixed (byte* ptr = &bytes[0]) { return (T)Marshal.PtrToStructure((IntPtr)ptr, typeof(T)); } }</code>
雖然首選的解決方案涉及固定和Marshal.PtrToStructure
,但在特定情況下,使用BinaryReader
類別解析資料可能會提供效能優勢。但是,必須評估具體的實現以確定此類增益是否顯著。
以上是如何有效率地將 C/C 位元組數組轉換為 C# 結構?的詳細內容。更多資訊請關注PHP中文網其他相關文章!