如何将 C# 中的二维数组传递给C++ DLL?
How to pass a two-dimensional array in C# to a C++ DLL?
我想将 C# 中的二维数组作为参数传递给 DLL C++函数(当我使用 CUDA C++ 时必须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 数组在内存中是连续的,因此不需要在两端复制所有这些内存。应按原样在 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: %dn", i, j, a[i * n + j]);
// Main calculations
return 0;
}
您可以使用类来封装指针、行和列,然后访问 传递一维数组,就好像它是标准二维数组一样。无需在函数中创建本地副本,因为 p 在调用中仍然有效。@mnistic的回答还指出,没有必要在 C# 中制作 1D 副本。
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;
};
返回表示为 2D 数组的数组元素的总和
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
}
以下是阿卜杜勒·阿齐兹回答的模板类:
template <class TdataType>
class Array2d {
public:
Array2d<TdataType>(TdataType* arr, size_t rows, size_t cols) : p(arr), cols(cols), rows(rows) {};
TdataType* 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:
TdataType* const p;
};
下面是使用它的示例:
auto my2dArray = Array2d<uint8_t>(inputArrayFromCsharp, numRows, numCols);
相关文章:
- 挂起和取消挂起一个文件DLL
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 导入库可以跨dll版本工作吗
- 从C++dll访问C#中的一行主要参数
- 链接到自行创建的dll失败
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 如何指定我希望我的LIB链接到的DLL文件?-Visual Studio 2019
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- C++:将外部库链接到dll库
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- 不同的Visual Studio版本中缺少.dll
- 从DLL中删除类的实例
- 如何包装第三方DLL在R中使用
- 使用c#访问c++dll中带有char*参数的函数时发生AccessViolationException
- 系统.将数组移交给c#中动态加载的c++DLL时发生AccessViolationException
- 为什么导入Mixed native/CLR lib.dll的本机C++应用程序没有在Mixed lib.dll中的外部变
- 当我使用 C++ 中的 C# dll 来使用 Selenium 时,存在异常处理问题
- Python ctypes:不会按预期加载 dll
- 在 C++/CLI 中将 .NET 事件从一个 DLL 引发到另一个 DLL