malloc で割り当てられた char など、データ配列へのポインターの配列を取るネイティブ関数があります。
void function(char** data, int nRows)
{
for (int i = 0; i < nRows; i++)
{
int nCols = _msize(data[i]);
for (j = 0; j < nCols; j++)
char val = data[i][j];
}
}
マネージド コードでは、PInvoke を介してその関数に渡す byte[] 配列の列挙があります。
unsafe void MyFunction(IEnumerable<byte[]> data)
{
var handles = data.Select(d => GCHandle.Alloc(d, GCHandleType.Pinned));
var ptrs = handles.Select(h => h.AddrOfPinnedObject());
IntPtr[] dataPtrs = ptrs.ToArray();
uint nRows = (uint)dataPtrs.Length;
function(dataPtrs, nRows);
handles.ToList().ForEach(h => h.Free());
}
[DllImport("function.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
static extern unsafe internal void function(IntPtr[] data, uint nRows);
ただし、ネイティブ コードで _msize を呼び出すと、ヒープが破損します。1 次元配列 char* と連結された byte[] 配列を組み合わせて stackalloc を使用したことを覚えています。しかし、さまざまなサイズの個々の byte[] 配列を使用した「ジャグ配列」のサポートが必要であるため、ポインター char** の配列が必要です。
_msize が stackalloc の場合のように正しく機能するように byte[] 配列を固定する方法は?