2013-03-08 72 views
3

我正在学习如何从C#代码中调用C代码。我想调用一个C函数返回一个二维数组。这个函数没有参数。下面是函数:如何从C代码返回一个2D 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#代码中执行该操作?

我很抱歉,如果这是重复的,但我发现有关二维数组的所有问题都涉及将它们从C#发送到C,而不是其他方式。

+0

你能告诉你你正在使用C#端的DLL导入函数吗?另外,你是否将内存设置为C端的任何内容;因为如果你不这样做,它会是随机的。 – 2013-03-08 20:14:54

回答

2

你正在通过Marshal.Copy一维数组,所以当然这就是你将要回来的。另外,foreach循环不能用于2d数组。

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

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]); 
     } 
} 
0

不要。在本机端使用适当大小的一维数组,然后所有东西都可以使用。否则,您需要将本地数组编组为指针数组,其中每个元素指向正确的内存块。然后,做什么evanmcdonnal告诉你,使用Marshal.Copy各自的超载。关于内存释放,你负责,或者更好的是,本地库是:安全的方式是将数组传回本地库,该库负责正确的释放。

0

我结束了使用Paul Michalik的建议。我使用了一维数组。这不是一个straightfoward的方式,但它确实工作得很好作为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