2009-04-28 8 views
9

W funkcji w mojej bibliotece DLL C++ wracam std :: string do mojej aplikacji C#. To dość dużo wygląda następująco:Zwracanie std :: string z biblioteki DLL C++ do programu C# -> Niepoprawny adres określony dla RtlFreeHeap

std::string g_DllName = "MyDLL"; 

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

Ale kiedy mój kod C# nazywa tę funkcję, otrzymuję ten post w moim oknem wyjściowym:

Invalid Address specified to RtlFreeHeap(00150000, 0012D8D8) 

deklaracji funkcji w C# wygląda następująco:

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

Z tego, co udało mi się znaleźć w Internecie, czasami ten komunikat pojawia się, gdy występuje niezgodność między wersją nowego (debugowanie lub wydanie itp.) Z usuwaniem. Ale nie jestem pewien, czy tak właśnie się dzieje w moim przypadku. Więc nie jestem pewien co dokładnie powoduje. Może MashallAs może mieć z tym coś wspólnego?

Wszelkie pomysły?

Dzięki!

+0

można sprawdzić, co znalazłeś to znaczy: a) jeżeli używasz poprawne (debug) Biblioteki do debugowania buduje etc oraz b) ten problem występuje w obu debugowania i wypuść kompilacje i spróbuj użyć/clr: pure zamiast/clr dla twojej biblioteki C++. – dirkgently

Odpowiedz

12

Udało mi się znaleźć problem. W ten sposób została wykonana definicja C#. Z tego, co rozumiem, użycie MarshallAs (UnmanagedType.LPStr) w połączeniu z typem zwracanym przez łańcuch powoduje, że spróbuje on zwolnić ciąg znaków, gdy zostanie zakończony. Ale ponieważ ciąg pochodzi z biblioteki DLL w C++, a najprawdopodobniej zupełnie innego menedżera pamięci, kończy się niepowodzeniem. I nawet jeśli to nie zawiodło, nie chcę, aby i tak został uwolniony.

Rozwiązanie znalazłem zmienić deklarację C#, aby ten (kod C++ jest bez zmian):

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

Więc to sprawia, że ​​jest tak, że po prostu zwraca wskaźnik do danych łańcuchowych. A następnie zmienić go na sznurku, przekazać go do Marshal.PtrToStringAnsi()

return Marshal.PtrToStringAnsi(GetDLLName()); 

i że zostanie owinięty w innej funkcji dla czystości.

znalazłem rozwiązanie z tej strony: http://discuss.fogcreek.com/dotnetquestions/default.asp?cmd=show&ixPost=1108

Powiązane problemy