web-dev-qa-db-ja.com

C ++配列をC#に戻す

エクスポートされたC++ DLLからC#プログラムに配列を返す方法がわからないようです。グーグルで見つけたのはMarshal.Copy()を使用してコピーすることだけでした。配列をバッファに入れますが、返そうとしている値が得られません。何が得られるのかわかりません。

これが私が試していることです:

エクスポートされた関数:

extern "C" __declspec(dllexport) int* Test() 
{
    int arr[] = {1,2,3,4,5};
    return arr;
}

C#部分:

    [DllImport("Dump.dll")]
    public extern static int[] test();

    static void Main(string[] args)
    {

        Console.WriteLine(test()[0]); 
        Console.ReadKey();


    }

戻り値の型int []は、マネージドとアンマネージドの違いのためにおそらく間違っていることを知っています。ここからどこに行くべきかわかりません。整数配列ではなく、文字配列を文字列に返す以外に答えが見つからないようです。

Marshal.Copyで取得した値が返される値ではない理由は、エクスポートされた関数の「arr」配列が削除されるためですが、誰かがこれをクリアできるかどうかは100%わかりません。それは素晴らしいことです。

18
David

Sriramが提案したソリューションを実装しました。誰かがここでそれを望む場合に備えて、それはあります。

C++では、次のコードを使用してDLLを作成します:

extern "C" __declspec(dllexport) int* test() 
{
    int len = 5;
    int * arr=new int[len+1];
    arr[0]=len;
    arr[1]=1;
    arr[2]=2;
    arr[3]=3;
    arr[4]=4;
    arr[5]=5;
        return arr;
}

extern "C" __declspec(dllexport) int ReleaseMemory(int* pArray)
{
    delete[] pArray;
    return 0;
}

DLLはInteropTestAppと呼ばれます。

次に、C#でコンソールアプリケーションを作成します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace DLLCall
{
    class Program
    {
        [DllImport("C:\\Devs\\C++\\Projects\\Interop\\InteropTestApp\\Debug\\InteropTestApp.dll")]
        public static extern IntPtr test();

        [DllImport("C:\\Devs\\C++\\Projects\\Interop\\InteropTestApp\\Debug\\InteropTestApp.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int ReleaseMemory(IntPtr ptr);

        static void Main(string[] args)
        {
            IntPtr ptr = test();
            int arrayLength = Marshal.ReadInt32(ptr);
            // points to arr[1], which is first value
            IntPtr start = IntPtr.Add(ptr, 4);
            int[] result = new int[arrayLength];
            Marshal.Copy(start, result, 0, arrayLength);

            ReleaseMemory(ptr);

            Console.ReadKey();
        }
    }
}

resultに値1,2,3,4,5が含まれるようになりました。

お役に立てば幸いです。

15
Gabriel