【问题标题】:Sending a 2D int array between C# and C++在 C# 和 C++ 之间发送 2D int 数组
【发布时间】:2014-04-02 18:46:37
【问题描述】:

我正在尝试创建一个解决方案,我可以在其中通过 CUDA 在 C# 程序中运行 2D int 数组,因此我目前尝试执行此操作的方法是创建一个可以处理 CUDA 的 C++ dll然后代码返回二维数组。我用来将数组发送到 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# 可能希望能够理解并接受它,但没有这样的运气。

有什么想法吗?

【问题讨论】:

  • 你的 C# 代码是什么样的?您使用的是 int[][] 还是 int[,]?
  • int[,] 我应该使用 int[][] 我不知道有区别吗?

标签: c# c++ arrays cuda


【解决方案1】:

当您在 C# 中使用 int[,] 时,int** 不是 C++ 中正确的对应类型。 int[][] 是 int 数组的数组,类似于 C++ 中的 int**;而int[,] 是一个具有二维索引的整数数组: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# 分配的数组。

最后,如果您只需要让 CUDA 内核在您的 C# 数据上运行,请查看一些为您处理所有 Pinvoke 危害的 cuda 包装器。像managedCuda(我维护这个项目)或cudafy 和其他一些。

【讨论】:

  • 非常感谢您,我会进一步研究这个问题,因为目前这对我来说是未知领域哈哈。
猜你喜欢
  • 2011-06-18
  • 2016-08-12
  • 2013-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-22
  • 1970-01-01
相关资源
最近更新 更多