Marsha.CopyTo() には IntPtr -> IntPtr のコピーメソッドがないので、kernel32.dll にある CopyMemory() を使う。
public static class Kern32 {
[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory(System.IntPtr dest, System.IntPtr src, uint count);
}
"T[] where T:struct" は Generic なので fixed ブロックでポインタに変換できない。Marsha.UnsafeAddrOfPinnedArrayElement() で配列の最初のポインタが取れるのでそれを利用する。その前に、GC されないように Pinned データに指定しておく。
public static class NativeArrayExtension {
public static void UnsafeCopyTo<T>(this NativeArray<T> src, T[] dst) where T:struct {
unsafe {
var pSrc = (System.IntPtr)src.GetUnsafePtr();
var hDst = GCHandle.Alloc(dst, GCHandleType.Pinned);
try {
var pDst = Marshal.UnsafeAddrOfPinnedArrayElement(dst, 0);
Kern32.CopyMemory(pDst, pSrc, (uint)(dst.Length * Marshal.SizeOf<T>()));
} finally {
hDst.Free();
}
}
}
}