2013-03-08 108 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