我想将C#中的二维数组作为参数传递给C ++ DLL中的函数(必须使用C ++,因为我使用的是CUDA C ++)。我尝试了很多事情,但未能使用数组或向量直接传递。我唯一能做的就是将其转换为一维数组,将其及其维传递给函数,然后将其转换回二维向量。这是C ++ DLL代码:
int Add(int* a, int m, int n)
{
int i, j, ans;
vector<vector<int>> A(m, vector<int>(n));
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
A[i][j] = a[i * n + j];
// Main calculations
return ans;
}
这是传递数组的C#代码:
[DllImport("CUDALib.dll")]
static extern int Add(int[] a, int m, int n);
private void PassArray(int[,] A)
{
int i, j, m, n, ans;
int[] a;
m = A.GetLength(0);
n = A.GetLength(1);
a = new int[m * n];
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
a[i * n + j] = A[i, j];
ans = Add(a, m, n);
}
我有更快,更有效,更直接的方法吗?
C#中的2D数组为contiguous in memory,因此不需要在任何一侧进行所有这种内存复制。您应该按原样在C#中传递数组指针:
[DllImport("CUDALib.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int Add(int[,] a, int m, int n);
static void PassArray(int[,] A)
{
int m = A.GetLength(0);
int n = A.GetLength(1);
int ans = Add(A, m, n);
}
然后像这样访问C ++中的各个元素:
extern "C" __declspec(dllexport) int Add(int* a, int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d %d: %d\n", i, j, a[i * n + j]);
// Main calculations
return 0;
}
您可以使用一个类来封装指针,行和列,然后访问通过了1D数组,就好像它是标准2D数组一样。由于p在调用中仍然有效,因此无需在函数内进行本地复制。 @mnistic的答案还指出,无需在C#中制作一维副本。
class Array2D {
public:
Array2D(int* p, size_t rows, size_t cols) : p(p), cols(cols), rows(rows){};
int* operator[](int row) { return p + row * cols; }
const size_t rows; // not needed but can be used for adding boundary checks
const size_t cols;
private:
int *const p;
};
返回表示为二维数组的数组元素之和
extern "C" __declspec(dllexport) int Add(int* p, int rows, int cols)
{
Array2D a(p, rows, cols);
int sum{};
for (int i = 0; i < rows; ++i)
for (int ii = 0; ii < cols; ++ii)
sum += a[i][ii];
return sum;
}
这里是显示其工作原理的测试
int main()
{
int* p = new int[6]{ 1, 2, 3, 4, 5, 6 };
Array2D a2d(p, 3, 2); // three rows, two cols
std::cout << a2d[0][0] << '\n'; // prints 1
std::cout << a2d[1][1] << '\n'; // prints 4
a2d[1][1] = 10;
std::cout << a2d[1][1] << '\n'; // now prints 10
std::cout << a2d[2][0] << '\n'; // prints 5
std::cout << a2d[2][1] << '\n'; // prints 6
}