Ho imparato a eseguire il marshalling delle importazioni di DLL non gestite in C# ... E mi sono imbattuto in qualcosa che non capisco.Delphi DLL stringa di ritorno da C# ... .NET 4.5 Heap Corruption ma .NET 4.0 funziona? Spiega per favore?
In Delphi, v'è una funzione che sta tornando da un Result := NewStr(PChar(somestring))
Procedure SomeFunc() : PChar; Stdcall;
Dalla mia comprensione, newstr solo alloca un buffer sul mucchio locali ... e somefunc sta tornando un puntatore ad esso.
In .NET 4.0 (Client Profile), via C# posso usare:
[DllImport("SomeDelphi.dll", EntryPoint = "SomeFunc", CallingConvention = CallingConvention.StdCall)]
public static extern String SomeFunc(uint ObjID);
Questo funziona (o come dice David, "sembra funzionare") bene in Windows 7 .NET 4.0 Client Profile. In Windows 8, ha un comportamento imprevedibile, che mi ha portato su questa strada.
Così ho deciso di provare lo stesso codice in .NET 4.5 e ho ottenuto errori di corruzione di heap. Ok, ora so che questo non è il modo corretto di fare le cose. Così ho scavare ulteriormente:
Sempre nel .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);
}
Questo funziona senza intoppi. La mia (novizia) preoccupazione è che NewStr() ha allocato questa memoria ed è rimasta lì per sempre. La mia preoccupazione non è valida?
In .NET 4.0, posso anche fare questo e non è mai genera un'eccezione:
[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;
}
Questo codice genera la stessa eccezione heap in 4.5, tuttavia. Questo mi porta a credere che il problema risieda nel fatto che in .Net 4.5, il marshaler sta provando a FreeCoTaskMem() e questo è ciò che sta generando le eccezioni.
quindi le domande:
Perché fa questo lavoro in .Net 4.0 e non 4.5?
Dovrei preoccuparmi dell'allocazione di NewStr() nella DLL nativa?
Se la risposta è "No" a # 2, il secondo esempio di codice è valido?
Per la cronaca, è la stessa macchina, stesso sistema operativo, stesso compilatore, stesso tutto. Basta fare clic con il tasto destro del mouse su Project -> change framework su 4.5 e viola, si blocca. Ad ogni modo, sono contento di averlo capito correttamente, e grazie come sempre per il tuo aiuto. –