如何将C int代码中的2D int数组返回给C#?

时间:2013-03-08 20:10:59

标签: c# c marshalling

我正在学习如何从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,而不是另一种方式。

3 个答案:

答案 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