C#でメモリのポインタ(IntPtr)と一次元配列間の値のコピーにはMarshal.Copyメソッド(名前空間:System.Runtime.InteropServices)を用います。
Marshal.Copyにはポインタから一次元配列へのコピー および 一次元配列からポインタへのコピーが用意されています。
一次元配列の型は、Single[], IntPtr[], Byte[], Single[], Int64[] , Int32[] , Int32[] , Int16[] , Double[]が指定可能です。
Mershal.Copyが可能なのは、あくまでも一次元配列が対象となります。
多次元配列(1次元、2次元、3次元…)と多次元配列間の値のコピーにはBuffer.BlockCopyメソッド(名前空間:System)を用います。
このメソッドでは、異なる次元の配列間、異なる型の配列間でメモリをコピーしてくれます。
異なる型の場合は、値のコピーではありません。
どちらかというと、C言語のCopyMemoryの挙動に似ています。
サンプルプログラム
// 一次元配列、二次元配列、三次元配列を確保(全て24バイト)
var arr1D = new byte[24] ;
var arr2D = new byte[6, 4];
var arr3D = new byte[2, 3, 4];
var arrUS = new ushort[12];
// メモリの確保(24バイト)
IntPtr ptr = Marshal.AllocHGlobal(24);
// 値の代入
for (byte i = 0; i < 24; i++)
{
Marshal.WriteByte(ptr, i, i);
}
// ポインタから一次元配列へコピー
Marshal.Copy(ptr, arr1D, 0, arr1D.Length);
// 一次元配列から二次元配列へコピー
Buffer.BlockCopy(arr1D, 0, arr2D, 0, arr1D.Length * sizeof(byte));
// 二次元配列から三次元次元配列へコピー
Buffer.BlockCopy(arr2D, 0, arr3D, 0, arr2D.Length * sizeof(byte));
// byte配列からushort配列へコピー
Buffer.BlockCopy(arr1D, 0, arrUS, 0, arr1D.Length * sizeof(byte));
// メモリの解放
Marshal.FreeHGlobal(ptr);
実行後の配列の値は以下のようになります。
ushort配列の結果が少しわかりづらいですが、byte配列の2バイト分が1つのushortの値として格納されます。
参考ページ
【C#】配列の中身をメモリで確認する方法
C言語の時は、ポインタの中身をメモリで参照する事が多かったのですが、C#をメインで触るようになってからは、メモリの中身を参照することは無くなってしまい、いざ、やってみようとすると、やり方がわかりづらかったので記事にしました。 まず、Visu...
コメント