在C#和C ++之间发送2D int数组

时间:2014-03-01 17:22:13

标签: c# c++ arrays cuda

我正在尝试创建一个解决方案,我可以通过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#可能有希望理解并接受它,但没有这样的运气。

有什么想法吗?

1 个答案:

答案 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和其他一些。