3

C# コードから C コードを呼び出す方法を学習しています。int の 2D 配列を返す 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

1次元配列を渡すMarshal.Copyので、もちろんそれが返されます。さらに、そのforeachループは2D配列では機能しません。

これは決して解決策ではなく、出発点にすぎません。

1)iarrを2次元配列にする-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

しないでください。ネイティブ側で適切なサイズの一次元配列を使用すると、すべてがすぐに機能します。それ以外の場合は、各要素が適切なメモリ チャンクを指すポインターの配列としてネイティブ配列をマーシャリングする必要があります。次に、Marshal.Copy のそれぞれのオーバーロードを使用して、evanmcdonnal の指示に従ってください。メモリの割り当て解除に関しては、あなたが担当するか、ネイティブ ライブラリの方が適切です。安全な方法は、適切な割り当て解除を処理するネイティブ ライブラリに配列を渡すことです。

于 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 に答える