从C ++到C#的数组 [英] Array from C++ to C#
问题描述
我试图将一个双精度数组(实际上是一个std :: vector,但在传输时进行转换)从c ++ dll转换为c#脚本(统一). 使用此处 https://stackoverflow.com/a/31418775 概述的方法.
I am trying to pass a double array (its actually a std::vector, but converted at transfer) from a c++ dll into a c# script (unity). Using the approach outlined here https://stackoverflow.com/a/31418775.
我可以统一在控制台上成功获得阵列打印的大小,但是由于我使用的是Xcode,而且它似乎没有COM,因此我无法使用"CoTaskMemAlloc"为阵列分配内存.
I can successfully get the size of the array printing on my console in unity however I am not able to use "CoTaskMemAlloc" to allocate memory for the array since I am using Xcode and it doesnt seem to have COM.
对于更多背景知识,此数组是GUI控件的一部分,c ++创建它,用户使用c#GUI进行编辑-因此,计划是在编辑完数组后将其传递回c ++.
For a little more background this array is part of a control for a GUI, c++ creates it and the user edits with the c# GUI - so the plan is to be able to pass the array back to c++ when it has been edited.
C++ code
extern "C" ABA_API void getArray(long* len, double **data){
*len = delArray.size();
auto size = (*len)*sizeof(double);
*data = static_cast<double*>(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的不足.
If I leave out the code concerning the array, the int passes just fine. So I beleive the method to be the right one, its just getting around the lack of CoTaskMemAlloc.
推荐答案
您应该能够使用malloc
在XCode中分配内存,并使用Marshal.FreeCoTaskMem
在C#中释放内存.为了能够释放它,您需要拥有IntPtr:
You should be able to allocate memory in XCode using malloc
and free it in C# using Marshal.FreeCoTaskMem
. To be able to free it however, you need to have the IntPtr for it:
C ++代码
extern "C" ABA_API void getArray(long* len, double **data)
{
*len = delArray.size();
auto size = (*len)*sizeof(double);
*data = static_cast<double*>(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()
.
From Memory Management I gathered that Marshal.FreeCoTaskMem
would most likely be implemented using free()
, so the fitting allocator would be malloc()
.
有两种方法可以确保:
- 使用
Marshal.AllocCoTaskMem
在CLI中分配内存,将其传递给本机以进行填充,然后使用Marshal.FreeCoTaskMem
在CLI中再次释放它. - 保持原样(本机使用
malloc()
分配内存),但不要在CLI中释放内存.取而代之的是,拥有另一个freeArray(double **data)
之类的本机函数,并在完成CLI使用后将其作为数组free()
给您.
- Allocate the memory in CLI using
Marshal.AllocCoTaskMem
, pass it to native to have it filled, and then free it in the CLI again usingMarshal.FreeCoTaskMem
. - Leave it as it is (native allocates memory with
malloc()
), but do not free the memory in CLI. Instead, have another native function likefreeArray(double **data)
and have itfree()
the array for you once CLI is done using it.
这篇关于从C ++到C#的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!