开发者

_msize() on managed data arrays?

There is a native function wich takes arrays of pointers to data arrays e.g. char allocated with 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]; 
  }
}

In managed code I have enumeration of byte[] arrays to pass to that function via 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);

However _msize call in native code leads to heap corruption. I remeber I used stackalloc with one dimensional array char* and concatenated byte[] arrays together. But I need support for 'jagged array' with individual byte[] arrays of different sizes hence the need for array of pointers char**.

How to pin the byte[] arrays so that _msize correctly works as in stackalloc case?


You will have to invoke native malloc (the same native malloc as used to compile the other code, usually by linking to the same CRT DLLs) to make this work correctly, as C# arrays cannot support _msize. That means you will have to manage the lifetime of this malloced memory yourself.


The memory was not allocated with something from the malloc family, hence _msize will not work.

This approach will not work when using C# to send data to the function.

Edit: Perhaps you should send along the column information as well.

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);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜