2009-04-28 6 views
9

için Belirtildi C++ DLL'mdeki bir işlevde, std :: string'i C# uygulamasına döndürüyorum. Hemen hemen şuna benzer:Bir std :: string bir C++ DLL'den bir C# programa döndürme -> Geçersiz Adres RtlFreeHeap

std::string g_DllName = "MyDLL"; 

extern "C" THUNDER_API const char* __stdcall GetDLLName() 
{ 
    return g_DllName.c_str(); 
} 

Ama C# kodu bu fonksiyonu çağırdığında, benim çıkış penceresinde bu mesajı alıyorum:

Invalid Address specified to RtlFreeHeap(00150000, 0012D8D8) 

C# işlevi beyanı şöyle:

[DllImport("MyDll", EntryPoint = "GetDLLName")] 
    [return: MarshalAs(UnmanagedType.LPStr)] 
    public static extern string GetDLLName(); 

Çevrimiçi olarak bulabildiğim kadarıyla, bazen bu ileti silme ile hangi yeni sürüm (hata ayıklama veya bırakma, vb.) Kullanıldığında arasında bir tutarsızlık olduğunda görüntülenir. Ama benim durumumda olup bittiğinden emin değilim. Bu yüzden buna neyin sebep olduğuna emin değilim. Belki de MashallA'ların bununla bir ilgisi olabilir?

Herhangi bir fikrin var mı?

Teşekkürler!

+0

kontrol edebilir Eğer yani) hata ayıklama vb oluşturur ve b) bu ​​sorun hem hata ayıklama oluşur için doğru (hata ayıklama) kütüphaneleri kullanıyorsanız ve ne buldum:

ben bu sayfadan çözüm buldu sürüm oluşturur ve c) C++ dll'iniz için/clr/pure yerine/clr: pure kullanmayı deneyin. – dirkgently

cevap

12

Sorunu bulmayı başardım. C# tanımının yapıldığı yol buydu. Anlayabildiğim kadarıyla, MarshallAs (UnmanagedType.LPStr) 'in dize döndürme türüyle birlikte kullanılması, onu bittiğinde dizgeyi serbest bırakmaya çalışacak şekilde yapar. Ancak, dize C++ DLL'den geldiği ve büyük olasılıkla tamamen farklı bir bellek yöneticisi olduğu için başarısız olur. Başarısız olsa bile, yine de serbest bırakılmasını istemiyorum. sadece dize verileri gösteren bir işaretçi döndürür, böylece

[DllImport("MyDll", EntryPoint = "GetDLLName")] 
public static extern IntPtr GetDLLName(); 

Yani bu yapar: buldum

çözüm bu C# beyanı (C++ kod değişmez) değiştirmekti. Ve sonra, bir dizeye değiştirmek Marshal.PtrToStringAnsi iletecek()

return Marshal.PtrToStringAnsi(GetDLLName()); 

Ve bu temizlik için bir başka fonksiyonu içine sarılmış olur etmek. http://discuss.fogcreek.com/dotnetquestions/default.asp?cmd=show&ixPost=1108