このタスクには、データを含むバイト配列を 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>
NewStuff
という名前の 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; }</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 中国語 Web サイトの他の関連記事を参照してください。