C#にて構造体(struct)からバイト配列(byte[])に内容のコピーをしたい時があります。
構造体とバイト配列のメモリーコピー方法は幾つかあり、またコピー速度も異なります。そのコピー方法を説明します。
サンプル構造体
unsafe struct Person { public fixed byte name[10]; public fixed byte Age[5]; }
上記の構造体をもとに以下説明をします。
バイト配列(byte[])を構造体(struct)に変換する
構造体のサイズだけbyte配列を確保します。
Person pos = new Person(); int size = Marshal.SizeOf(pos); byte[] buffer = new byte[size]; //bufferにデータコピー
Marshalを使用して構造体にコピーする
IntPtr ptr = Marshal.AllocHGlobal(size); Marshal.Copy(buffer, 0, ptr, size); pos = (Person)Marshal.PtrToStructure(ptr, typeof(Person)); Marshal.FreeHGlobal(ptr);
GCHandleを使用して構造体にコピーする
GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned); pos = (Person)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(Person)); gch.Free();
ポインタで直接構造体にコピーする
unsafe { fixed (byte* pbytes = buffer) { pos = *(Person*)pbytes; } }
構造体(struct)をバイト配列(byte[])に変換する
Marshalを使用してバイト配列にコピーする
int size = Marshal.SizeOf(pos); byte[] bytes = new byte[size]; //アンマネージメモリからメモリを割り当て IntPtr ptr = Marshal.AllocHGlobal(size); //マネージオブジェクトからアンマネージメモリにデータをマーシャリング Marshal.StructureToPtr(pos, ptr, false); //アンマネージデータをマネージのbyte[]にコピーする Marshal.Copy(ptr, bytes, 0, size); Marshal.FreeHGlobal(ptr);
GCHandleを使用してバイト配列にコピーする
int size = Marshal.SizeOf(pos); byte[] bytes = new byte[size]; GCHandle gchw = GCHandle.Alloc(bytes, GCHandleType.Pinned); Marshal.StructureToPtr(pos, gchw.AddrOfPinnedObject(), false); gchw.Free();
ポインタで直接バイト配列にコピーする
int size = Marshal.SizeOf(pos); byte[] bytes = new byte[size]; unsafe { fixed (byte* pbytes = bytes) { *(Person*)pbytes = pos; } }