我正在尝试创建一个解决方案,我可以通过CUDA在C#程序中运行2D int数组,所以我正在尝试这样做的方法是创建一个可以处理CUDA的C ++ DLL代码然后返回2D数组。我用来将我的数组发送到dll并再次返回的代码如下所示。
#include "CudaDLL.h"
#include <stdexcept>
int** cudaArrayData;
void CudaDLL::InitialiseArray(int arrayRows, int arrayCols, int** arrayData)
{
cudaArrayData = new int*[arrayCols];
for(int i = 0; i < arrayCols; i++)
{
cudaArrayData[i] = new int[arrayRows];
}
cudaArrayData = arrayData;
}
int** CudaDLL::ReturnArray()
{
return cudaArrayData;
}
但问题是我在返回时遇到C#错误,“无法编组'返回值':无效的托管/非托管类型组合。”我的希望是,如果我将数组返回作为指针C#可能有希望理解并接受它,但没有这样的运气。
有什么想法吗?
答案 0 :(得分:0)
当您在C#中使用int[,]
时,int**
在C ++中不是正确的对应类型。 int[][]
是一个int数组的数组,类似于C ++中的int**
;而int[,]
是一个包含2D索引的整数数组:index = x + y * width
。在C#/ C ++互操作中使用int**
很困难,因为你有许多指向托管或非托管内存的指针,这些内存不能直接从一个到另一个访问(参见下文)。
你已经在InitialiseArray(..., int** arrayData)
中读到了内存中的某个地方而不是数组值,因为你没有传递一个带有指向int数组的指针的数组,你传递了一个int数组。
当你在ReturnArray()中返回int**
时,你的问题是.net不知道如何将指针解释为指针。
要解决此问题,请在C ++端仅使用int*
并且不要将数组作为函数返回值返回,这只会为您提供指向非托管数组的指针,而不是托管内存中的整个数据。可以从C#中使用它,但可能不是你想要的方式。使用在C#中分配的数组作为void ReturnArray(int* retValues)
中的函数参数将数据复制到。
另一个问题是数据复制和内存分配。如果你在C#中处理内存,你可以避免所有这些步骤,即禁止垃圾收集器移动你的数据(它在清理未使用的对象时这样做)。使用固定的{}语句或通过GCHandle.Alloc(array,GCHandleType.Pinned)手动执行。这样,您可以直接在C ++中使用C#已分配的数组。
最后,如果您只需要在C#数据上运行CUDA内核,请查看一些处理所有Pinvoke危险的cuda包装器。像managedCuda(我维护这个项目)或cudafy和其他一些。