1

有一个本机函数,它采用指向数据数组的指针数组,例如用 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 调用会导致堆损坏。我记得我将 stackalloc 与一维数组 char* 和串联的 byte[] 数组一起使用。但我需要支持具有不同大小的单个字节 [] 数组的“锯齿状数组”,因此需要指针数组 char**。

如何固定 byte[] 数组以使 _msize 像在 stackalloc 情况下一样正确工作?

4

2 回答 2

0

内存没有分配给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);
}
于 2011-03-15T19:21:15.293 回答
0

您必须调用本机malloc(与malloc用于编译其他代码的本机相同,通常通过链接到相同的 CRT DLL)才能使其正常工作,因为 C# 数组不支持_msize. 这意味着您必须自己管理此malloced 内存的生命周期。

于 2011-03-15T19:25:24.310 回答