在 C# 位元組數組中高效處理 C/C 資料結構
C# 和 C/C 之間的互通通常需要資料結構轉換。 本文介紹了以位元組數組形式接收資料並將其轉換為可用的 C# 結構體的常見場景。
位元組數組資料結構的解析策略
C# 中成功從位元組陣列解析 C/C 結構的關鍵在於以下步驟:
符合 C# 結構體定義: 建立一個鏡像 C/C 結構體佈局的 C# 結構體。 使用 [StructLayout]
和 [FieldOffset]
.
記憶體固定:使用GCHandle
來固定位元組數組,防止垃圾收集在解析過程中重新定位它。
直接記憶體轉換: 使用 Marshal.PtrToStructure
直接將固定記憶體位址轉換為您定義的 C# 結構體。 與其他方法相比,這提供了卓越的性能。
記憶體釋放: 至關重要的是,使用 handle.Free()
釋放固定內存,以避免資料處理後發生記憶體洩漏。
說明性範例:C 到 C# 結構體轉換
讓我們考慮一個 C 結構體 (OldStuff
) 及其等效的 C# 結構體 (NewStuff
):
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# 結構:
<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; // Filler is omitted in C# as it's not needed for data access. }</code>
以下 C# 方法示範了位元組數組解析:
<code class="language-csharp">public NewStuff ByteArrayToNewStuff(byte[] bytes) { GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); try { return (NewStuff)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NewStuff)); } finally { handle.Free(); } }</code>
效能最佳化
雖然BinaryReader
提供了一種替代方案,但Marshal.PtrToStructure
通常透過直接轉換記憶體位址來提供卓越的效能,避免格式解釋開銷。 這種直接方法對於大型資料集特別有益。
透過採用這些技術,開發人員可以實現對 C# 位元組數組中嵌入的 C/C 資料結構的高效且高效能的解析。
以上是如何在C#中高效率地從位元組數組解析C/C資料結構?的詳細內容。更多資訊請關注PHP中文網其他相關文章!