3

我正在学习如何从我的 C# 代码中调用 C 代码。我想调用一个返回二维整数数组的 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,而不是相反。

4

3 回答 3

2

您正在传递Marshal.Copy一个一维数组,所以当然这就是您要返回的内容。此外,foreach 循环不适用于二维数组。

这绝不是一个解决方案,只是一个起点;

1)使 iarr 二维数组 -int[] iarr = new int[9][9];

2)使您的打印功能嵌套for循环 -

 for (int i = 0; i < 9; i++)
 {
      for (int j = 0; i < 9; j++)
      {
           Console.WriteLine(iarr[i][j]);
      }
 }
于 2013-03-08T20:17:32.423 回答
0

不。在本机端使用适当大小的一维数组,然后一切都可以开箱即用。否则,您将需要将本机数组编组为指针数组,其中每个元素都指向正确的内存块。然后,按照 evanmcdonnal 告诉您的操作,使用 Marshal.Copy 的相应重载。关于内存释放,您负责,或者更好的是,本机库是:安全的方法是将数组传递回本机库,该库负责正确的释放。

于 2013-03-08T20:44:24.410 回答
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
于 2015-06-26T03:25:44.443 回答