_msize () для управляемых массивов данных? - PullRequest
1 голос
/ 15 марта 2011

Существует встроенная функция, которая берет массивы указателей на массивы данных, например, char, выделенный с помощью malloc.

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]; 
  }
}

В управляемом коде у меня есть перечисление массивов byte [] для передачи этой функции через PInvoke

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 в нативном коде приводит к повреждению кучи. Я помню, я использовал stackalloc с одномерным массивом char * и сцепленными массивами byte [] вместе. Но мне нужна поддержка «зазубренного массива» с отдельными массивами byte [] разных размеров, поэтому мне нужен массив указателей char **.

Как закрепить массивы byte [], чтобы _msize работал правильно, как в случае с stackalloc?

Ответы [ 2 ]

0 голосов
/ 15 марта 2011

Вам нужно будет вызвать нативный malloc (тот же нативный malloc, который использовался для компиляции другого кода, обычно путем ссылки на те же библиотеки CRT DLL), чтобы это работало правильно, так как массивы C # не могут поддерживать _msize , Это означает, что вам придется самостоятельно управлять временем жизни этой malloc редактируемой памяти.

0 голосов
/ 15 марта 2011

Памяти не было выделено что-то из семейства malloc, поэтому _msize не будет работать.

Этот подход не будет работать при использовании C # для отправки данных в функцию.

Редактировать: Возможно, вам следует также отправить информацию о столбце.

void function(char** data, int nRows, int* colSize)
{
     /* colSize has nRows elems, containing the columns per row:
      * int nCols = colSize[i];
      */
}

[DllImport("function.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
static extern unsafe internal void function(IntPtr[] data, uint nRows, int[] colSize);

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(); 
    var cols = data.Select(x => x.Length).ToArray();
    function(dataPtrs, (uint)dataPtrs.Length, cols);   
    handles.ToList().ForEach(h => h.Free());
    GC.KeepAlive(dataPtrs);
    GC.KeepAlive(cols);
}
...