我正在学习如何从C#代码中调用C代码。我想调用一个返回二维int数组的C函数。此函数不带参数。这是功能:
extern "C" _declspec(dllexport) int** intMatrixReturn()
{
int** A = (int**)malloc(3 * sizeof(int *));
for(int i = 0; i < 3; i++)
{
A[i] = (int*)malloc(3 * sizeof(int));
for(int j = 0; j < 3; j++)
{
A[i][j] = i * j;
}
}
return A;
}
这就是我尝试使用C#代码访问数组的方法:
IntPtr ip = intArrayReturn();
int[] iarr = new int[9];
Marshal.Copy(ip, iarr, 0, 9);
foreach (var item in iarr)
{
Console.WriteLine(item);
}
这是我的控制台输出:
1
2
3
4218
86245572
86252624
0
0
0
我认为我的问题是我的C#代码。如何读取从C函数返回的2D int数组?此外,垃圾收集器是否释放了存放2D阵列的内存,或者我应该在C#代码中执行此操作?
我很抱歉,如果这是重复的,但我发现的有关2D数组的所有问题都涉及将它们从C#发送到C,而不是另一种方式。
答案 0 :(得分:2)
你正在传递Marshal.Copy
一维数组,所以当然这就是你要回来的东西。另外,foreach循环不适用于2d数组。
这绝不是一个解决方案,只是一个起点;
1)使iarr成为一个二维数组 - int[] iarr = new int[9][9];
2)使你的打印功能嵌套为循环 -
for (int i = 0; i < 9; i++)
{
for (int j = 0; i < 9; j++)
{
Console.WriteLine(iarr[i][j]);
}
}
答案 1 :(得分:0)
别。在原生方面使用适当大小的一维数组,然后一切都开箱即用。否则,您需要将本机数组编组为指针数组,其中每个元素指向正确的内存块。然后,使用Marshal.Copy的相应重载来做evanmcdonnal告诉你的事情。关于内存释放,你负责或者更好,本机库是:安全的方法是将数组传递回本地库,它负责正确的释放。
答案 2 :(得分:0)
我最终使用了Paul Michalik
的建议。我用过一维数组。这不是一种直接的方式,但它确实很适合2D:
C方:
extern "C" {
struct Matrix
{
int size1; // rows number
int size2; // cols number
int *data;
};
Matrix* intMatrixReturn(int size1, int size2) {
Matrix *m = (Matrix*)malloc(sizeof(Matrix) * 1);
m->data = (int*)malloc(sizeof(int) * size1 * size2);
m->size1 = size1;
m->size2 = size2;
for (int i = 0; i < size1; i++)
{
for (int j = 0; j < size2; j++)
{
m->data[i*size2+j] = i*size2+j;
}
}
return m;
}
}
C#方:
[StructLayout(LayoutKind.Sequential)]
public struct Matrix
{
public int size1;
public int size2;
public IntPtr data;
}
[DllImport(@"dllname.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr intMatrixReturn(int size1, int size2);
static void Main(string[] args)
{
int size1 = 3; // rows
int size2 = 3; // cols
IntPtr p1 = intMatrixReturn(size1, size2);
Matrix m1 = (Matrix)Marshal.PtrToStructure(p1, typeof(Matrix));
int[] tmp = new int[m1.size1 * m1.size2];
IntPtr pd2 = m1.data;
Marshal.Copy(pd2, tmp, 0, m1.size1 * m1.size2);
for (int i = 0; i < m1.size1; i++)
{
for (int j = 0; j < m1.size2; j++)
{
Console.Write(tmp[i * m1.size2 + j] + " ");
}
Console.WriteLine();
}
}
<强>输出:强>
0 1 2
3 4 5
6 7 8