2013-07-13 3 views
8

Я не могу понять, как вернуть массив из экспортированной библиотеки C++ в мою программу на C#. Единственное, что я нашел в googling, это использовать Marshal.Copy(), чтобы скопировать массив в буфер, но это не дает мне значения, которые я пытаюсь вернуть, я не знаю, что это дает мне.Возвращает массив C++ в C#

Вот что я пытался:

экспортируемой функции:

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%, если кто-то может прояснить это, что было бы здорово.

+0

http://stackoverflow.com/questions/3776485/marshal-c-int-array-to-c-sharp Это может помочь вам –

+1

[Не хорошо.] (Http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – chris

+0

Спасибо, Крис, я был так напуган, что забыл, что я делаю. Я собираюсь немного изменить свой код, таким образом, у меня есть экспортированная функция в адресе в буфер и заполнить буфер оттуда. – David

ответ

10

Я реализовал решение, предложенное Шрирамом. В случае, если кто-то хочет его здесь.

В 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); 
      ptr = IntPtr.Add(ptr, 4); 
      int[] result = new int[arrayLength]; 
      Marshal.Copy(ptr, result, 0, arrayLength); 

      ReleaseMemory(ptr); 

      Console.ReadKey(); 
     } 
    } 
} 

result теперь содержит значения 1,2,3,4,5.

Надеюсь, что это поможет.

+3

Это не поможет. Вам нужно будет показать, как вы знаете магию «5» и как вы собираетесь выпускать массив, чтобы не было постоянной утечки памяти. –

+3

@Hans, вопрос был «Возвращать массив C++ в C#». Да, это помогает. – user1764961

+4

Хорошо, тогда просто подумайте об этом предостерегающем предупреждении бесчисленным гуглерам, которые когда-нибудь найдут ваш ответ и не поймут, что код просачивает память, как сито, и произвольно бомбит с нарушениями доступа. –

Смежные вопросы