我正在尝试从我的C#代码中调用CPP方法,该方法将返回以下结构。
CPP:
struct ArrayD
{
int count;
float* arrayData;
}
C#:
struct ArrayD
{
int count;
IntPtr arrayData;
}
使用CPP代码中的std :: make_unique初始化数组,并返回结构。
但是当我尝试使用Marshal.Copy将IntPtr复制到C#中的float数组时,我尝试读取/写入损坏的内存错误。
我确认在dll导出过程中丢失了对数组的引用,有没有办法在整个代码中保留引用或数据。
下面是代码
extern "C" ArrayD _declspec(dllexport) __stdcall CPPMetho()
{
auto arrayd = std::make_unique<ArrayD>();
arrayd.count = 10;
auto arrayData = std::make_unique<float[]>(arrayd.count);
// Fill data to the array created above
arrayd.arrayData= arrayData .get();
return arrayd;
}
我在C#代码中调用上述API,我从数组中获得“计数”的值,但是当我尝试封送数组数据时,我得到了异常。
任何想法如何将引用保留在C#中以启用封送处理
答案 0 :(得分:0)
这两行是问题所在:
auto arrayData = std::make_unique<float[]>(arrayd.count);
arrayd.arrayData= arrayData .get();
第一个创建包裹数组的智能指针。第二行保存指向包装好的数组的指针。
然后,当您从函数返回时,arrayData
的生存期结束并且被破坏,然后释放包装的数组。这使您保存的指针无效,因为它现在指向未分配的内存。
解决方案是在结构中也使用智能指针,或者更好的方法是使用std::vector<float>
(在这种情况下,您根本不需要结构)。
答案 1 :(得分:0)
最少的更改是:
ArrayD arrayd = {};
arrayd.count = 10;
// std::unique_ptr<float[]> arrayData
// don't let auto hide what the types really are!
auto arrayData = std::make_unique<float[]>(arrayd.count);
// Fill data to the array created above
arrayd.arrayData = arrayData.release();
return arrayd;
请注意,我已经更改了arrayd
的分配。现在,它是一个堆栈变量。并且为arrayData
添加了release()
,以使std::unique_ptr<>
创建的std::make_unique<float[]>
不会被释放。您必须创建一个伴随FreeArrayD(ArrayD& arrayData)
来释放分配的内存。