L’app Web ASP.NET che chiama Delphi DLL sul server Web IIS si blocca quando si restituisce la stringa PChar

Funziona bene se non restituisco nulla, o restituisco un intero. Ma se provo a restituire un PChar, cioè ..

result := PChar('') or result:= PChar('Hello') 

L’app Web si blocca e osservo che il suo conteggio della memoria aumenta gradualmente nel task manager.

La cosa strana è che la DLL funziona bene sul server di debug VStudio o tramite un’app C #. L’unica cosa che posso pensare che farebbe la differenza è che il server IIS è in esecuzione in Windows a 64 bit.

Tuttavia, non sembra essere un problema di compatibilità perché posso scrivere correttamente su file di testo e fare altre cose dalla DLL … NON posso restituire una stringa PChar.

Ho provato a usare PWideChar, ho provato a restituire “qualcosa \ 0”, ho provato tutto quello che potevo pensare. Sfortunatamente no.

 [DllImport("TheLib.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] private static extern string SomeFunction(); string result = SomeFunction(); 

Delphi:

 library TheLib; function SomeFunction() : PChar export; stdcall; begin return PChar(''); end; exports SomeFunction 

L’analisi di Dampsquid è corretta, quindi non lo ripeterò. Tuttavia, preferisco una soluzione diversa che mi sembra più elegante. La mia soluzione preferita per un tale problema è usare Delphi Widestring che è un BSTR .

Sul lato Delphi lo scrivi così:

 function SomeFunction: Widestring; stdcall; begin Result := 'Hello'; end; 

E sul lato C # lo fai in questo modo:

 [DllImport(@"TheLib.dll")] [return: MarshalAs(UnmanagedType.BStr)] private static extern string SomeFunction(); 

E questo è tutto. Poiché entrambe le parti utilizzano lo stesso allocatore COM per l’allocazione di memoria, tutto funziona correttamente.

Aggiornamento 1

@NoPyGod fa notare che questo codice ha esito negativo con un errore di runtime. Avendo esaminato ciò, ritengo che sia un problema alla fine di Delphi. Ad esempio, se lasciamo il codice C # così com’è e usiamo quanto segue, gli errori vengono risolti:

 function SomeFunction: PChar; stdcall; begin Result := SysAllocString(WideString('Hello')); end; 

Sembrerebbe che Delphi restituisca i valori di tipo WideString non gestiti come dovrebbero essere. I parametri out e i parametri var sono gestiti come previsto. Non so perché i valori di ritorno falliscono in questo modo.

Aggiornamento 2

Risulta che il WideString restituito da Delphi ABI per WideString non è compatibile con gli strumenti Microsoft. Non dovresti usare WideString come tipo di ritorno, ma restituirlo tramite un parametro out . Per maggiori dettagli vedi Perché un WideString non può essere usato come valore di ritorno di una funzione per l’interoperabilità?

Non è ansible restituire una stringa del genere, la stringa è locale alla funzione e verrà liberata non appena la funzione ritorna lasciando il PChar restituito che punta a una posizione non valida.

è necessario passare un puntatore per essere riempiti all’interno della DLL, creare dynamicmente la stringa e liberarla nuovamente nel codice c # oppure creare un buffer statico in yout DLL e restituirlo.

Di gran lunga il modo più sicuro è quello di passare un puntatore nella funzione cioè

 function SomeFunction( Buffer: PChar; MaxLength: PInteger ): wordbool; stdcall; { // fill in the buffer and set MaxLength to length of data } 

dovresti impostare MaxLength sul sixe del buffer prima di chiamare la tua DLL in modo che la dll possa controllare che ci sia spazio sufficiente per i dati da restituire.

prova ad abilitare le applicazioni a 32 bit nelle impostazioni avanzate del pool di applicazioni:

inserisci la descrizione dell'immagine qui