从C ++到C#的数组

我试图将一个双数组(它实际上是一个std :: vector,但转换后转换)从c ++ dll传递到ac#script(unity)。 使用此处概述的方法https://stackoverflow.com/a/31418775 。

我可以在我的控制台上成功地获得arrays打印的大小但是我无法使用“CoTaskMemAlloc”来为arrays分配内存,因为我使用Xcode并且它似乎没有COM。

对于更多的背景,这个数组是GUI控件的一部分,c ++创建它并且用户使用c#GUI进行编辑 – 因此计划是在编辑时将数组传递回c ++。

C++ code extern "C" ABA_API void getArray(long* len, double **data){ *len = delArray.size(); auto size = (*len)*sizeof(double); *data = static_cast(CoTaskMemAlloc(size)); memcpy(*data, delArray.data(), size); } C# code [DllImport("AudioPluginSpecDelay")] private static extern void getArray (out int length,[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] out double[] array); int theSize; double[] theArray; getArray(out theSize, out theArray); 

如果我省略了关于数组的代码,那么int传递就好了。 所以我相信这个方法是正确的,它只是绕过缺乏CoTaskMemAlloc。

您应该能够使用malloc在XCode中分配内存,并使用Marshal.FreeCoTaskMem在C#中释放它。 但是,为了能够释放它,你需要有它的IntPtr:

C ++代码

 extern "C" ABA_API void getArray(long* len, double **data) { *len = delArray.size(); auto size = (*len)*sizeof(double); *data = static_cast(malloc(size)); memcpy(*data, delArray.data(), size); } 

C#代码

 [DllImport("AudioPluginSpecDelay")] private static extern void getArray(out int length, out IntPtr array); int theSize; IntPtr theArrayPtr; double[] theArray; getArray(out theSize, out theArrayPtr); Marshal.Copy(theArrayPtr, theArray, 0, theSize); Marshal.FreeCoTaskMem(theArrayPtr); // theArray is a valid managed object while the native array is already freed 

编辑

从内存管理我收集到Marshal.FreeCoTaskMem最有可能使用free() ,因此拟合分配器将是malloc()

有两种方法可以确定:

  1. 使用Marshal.AllocCoTaskMem在CLI中分配内存,将其传递给native以使其填充,然后使用Marshal.FreeCoTaskMem再次在CLI中释放它。
  2. 保持原样(本机使用malloc()分配内存),但不要在CLI中释放内存。 相反,拥有另一个本机函数,如freeArray(double **data)并在使用它完成CLI后为它free()数组。

我不是Unity的专家,但Unity似乎依赖于Mono的C#脚本支持 。 看一下这个文档页面:

单声道内存管理

我们可以假设您需要在C ++端使用与平台相关的代码,您需要在Windows中使用CoTaskMemAlloc / CoTaskMemFree,在CSS中使用GLib内存函数g_malloc()和g_free()(如iOS,Android等) 。

如果您可以控制所有代码,C ++和C#,那么实现它的最简单方法是在C#脚本中进行所有内存分配/释放。

示例代码(未经测试):

 //C++ code extern "C" ABA_API long getArrayLength(){ return delArray.size(); } extern "C" ABA_API void getArray(long len, double *data){ if (delArray.size() <= len) memcpy(data, delArray.data(), delArray.size()); } // C# code [DllImport("AudioPluginSpecDelay")] private static extern int getArrayLength(); [DllImport("AudioPluginSpecDelay")] private static extern void getArray(int length,[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] double[] array); int theSize = getArrayLength(); double[] theArray = new double[theSize]; getArray(theSize, theArray);