2013-07-13 23 views
8

Dışa aktarılan C++ DLL dosyasından C# programıma bir dizinin nasıl döndürüleceğini anlayamıyorum. Googling'ten bulduğum tek şey diziyi bir arabelleğe kopyalamak için Marshal.Copy() kullanıyordu, ama bu bana geri vermeye çalıştığım değerleri vermiyor, bana ne verdiğini bilmiyorum. İşte C++ dizgesini döndür C#

ben çalışıyorum budur:

Dışa fonksiyonu:

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

C# kısmı:

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

    static void Main(string[] args) 
    { 

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


    } 

ben döndürme türü int [] çünkü muhtemelen yanlış olduğunu biliyorum yönetilen/yönetilmeyen farklılıklar, buradan nereye gideceğimi bilmiyorum. Ben hiçbir şey için bir cevap bulmak için görünmüyor, ancak tamsayı dizileri değil karakter dizileri dizelere döndürüyor.

Marshal.Copy ile elde ettiğim değerlerin neden dönmediğimi anladım çünkü dışa aktarılan işlevdeki 'arr' dizisi silindi, ancak% 100 emin değilim Bunu temizleyebilir, bu harika olurdu.

+0

http://stackoverflow.com/questions/3776485/marshal-c-int-array-to-c-sharp Bu –

+1

size yardımcı olabilecek [iyi değil.] (Http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-out-onun-kapsamı) – chris

+0

Teşekkürler Chris, ben bu kadar yakalanmıştım ne yaptığımı unuttum. Kodumu biraz değiştireceğim, bu şekilde ihraç ettiğim fonksiyonun arabelleğe girmesini ve arabayı oradan dolduracağım. – David

cevap

10

Sriram'ın önerdiği çözümü hayata geçirdim. Birisi burada olmasını istiyorsa öyle. DLL InteropTestApp adı verilecek

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; 
} 

: C

bu kodu içeren bir DLL oluşturmak ++.

Daha sonra C# uygulamasında bir konsol uygulaması oluşturursunuz.

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 şimdi değerleri 1,2,3,4,5 içeriyor.

Bu yardımcı olur umarım.

+3

Bu yardımcı olmuyor. "5" sihrini nasıl bildiğini ve diziyi nasıl bırakacağınızı göstermeniz gerekir, böylece kalıcı bellek sızıntısı olmaz. –

+3

@Hans, soru "Dönüş C++ dizisi C#" idi. Yani, evet, yardımcı oluyor. – user1764961

+4

Pekala, o zaman, yorumunuzu bir gün içinde cevabınızı bulabileceğiniz ve kodun bir elek gibi bellek sızdıran ve erişim ihlalleriyle keyfi olarak bombalandığı konusunda hiçbir ipucu bulamayan çok sayıda kullanıcı için uyarıcı bir uyarı olarak düşünün. –