Dowiedziałem się o ładowaniu niezarządzanych importów DLL do C# ... I natknąłem się na coś, czego nie całkiem rozumiem.Delphi DLL zwraca ciąg z C# ... .NET 4.5 Heap Corruption ale .NET 4.0 działa? Wytłumacz, proszę?
W Delphi, jest to funkcja, która zwraca Result := NewStr(PChar(somestring))
z Procedure SomeFunc() : PChar; Stdcall;
Z mojego zrozumienia, NewStr tylko przydziela bufor na lokalnej stercie ... i SomeFunc zwraca wskaźnik do niego.
W .NET 4.0 (Profil klienta), za pośrednictwem C# można użyć:
[DllImport("SomeDelphi.dll", EntryPoint = "SomeFunc", CallingConvention = CallingConvention.StdCall)]
public static extern String SomeFunc(uint ObjID);
To działa (lub jak mówi David "wydaje się działać") grzywny w Windows 7 .NET 4.0 Client Profile. W systemie Windows 8 ma nieprzewidywalne zachowanie, które doprowadziło mnie do tej drogi.
Postanowiłem więc wypróbować ten sam kod w .NET 4.5 i dostałem błędy korupcji sterty. Okay, więc teraz wiem, że to nie jest właściwy sposób robienia rzeczy. Więc wbijam dalej:
Jeszcze w .NET 4.5
[DllImport("SomeDelphi.dll", EntryPoint = "SomeFunc", CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr _SomeFunc();
public static String SomeFunc()
{
IntPtr pstr = _SomeFunc();
return Marshal.PtrToStringAnsi(pstr);
}
To działa bez zarzutu. Mój (nowicjusz) problem polega na tym, że NewStr() przydzielił tę pamięć i po prostu siedzi tam na zawsze. Czy moja troska nie jest ważna?
W .NET 4.0, mogę nawet tego robić i nigdy nie zgłasza wyjątek:
[DllImport("SomeDelphi.dll", EntryPoint = "SomeFunc", CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr _SomeFunc();
public static String SomeFunc()
{
String str;
IntPtr pstr = _SomeFunc();
str = Marshal.PtrToStringAnsi(pstr);
Marshal.FreeCoTaskMem(pstr);
return str;
}
Ten kod rzuca ten sam wyjątek sterty w 4,5, jednak. To prowadzi mnie do przekonania, że problem polega na tym, że w .Net 4.5, Marshaler próbuje FreeCoTaskMem() i to jest to, co rzuca wyjątki.
Więc pytania:
Dlaczego to działa w .NET 4.0, a nie 4.5?
Czy powinienem się martwić o alokację NewStr() w macierzystej bibliotece DLL?
Jeśli odpowiedź "Nie" na nr 2, to drugi przykład kodu jest ważny?
Dla rekordu jest to ta sama maszyna, ten sam system operacyjny, ten sam kompilator, to samo. Kliknij prawym przyciskiem myszy Projekt -> zmień frameworię na 4.5 i viola, to się zawiesi. W każdym razie cieszę się, że zrozumiałem to poprawnie i dziękuję jak zawsze za pomoc. –