2014-03-01 32 views
0

我想創建一個解決方案,我可以通過CUDA在C#程序內運行一個二維詮釋數組,所以我目前採取的做法是做到這一點創建一個可以處理CUDA代碼的C++ dll,然後返回二維數組。下面是我用來將數組發送給dll並返回的代碼。發送一個C#和C++之間的二維詮釋數組

#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

你的C#代碼是怎樣的?你使用int [] []還是int [,]? – kunzmi

+0

int [,]我應該使用int [] []我tbh不知道有什麼區別? – AdamWTF

回答

0

由於您在C#中使用int[,],因此int**不是C++中正確的對應類型。 int[][]是一個整數數組的數組,類似於C++中的int**;而int[,]是具有2D索引的整數的一個數組:index = x + y * width。在C#/ C++ interop中使用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和其他一些。

+0

非常感謝你,我會進一步考慮這一點,因爲它目前是我的未知領域哈哈。 – AdamWTF