Domanda

Ho una DLL Delphi con una funzione definita come:

funzione SubmitJobStringList (elenco lavori: tStringList; var jobno: intero): intero;

Lo chiamo da C #. Come dichiaro il primo parametro come tStringList non esiste in C #. Al momento ho la dichiarazione come:

[DllImport("opt7bja.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int SubmitJobStringList(string[] tStringList, ref int jobno);

Ma quando lo chiamo ottengo un'eccezione di violazione dell'accesso alla memoria.

Qualcuno sa come passare correttamente a una tStringList da C #?

È stato utile?

Soluzione

Molto probabilmente non avrai fortuna con questo. TStringList è molto più di un semplice array, è una classe completa e gli esatti dettagli di implementazione possono differire da quanto è possibile con .NET. Dai un'occhiata al codice sorgente VCL di Delphi (ovvero, se ce l'hai) e prova a scoprire se puoi ricostruire la classe in C # e passala con l'aiuto del tuo migliore amico, Interop Marshaller. Si noti che anche il tipo di stringa Delphi è diverso dal tipo di stringa .NET e, passandolo senza dire al marshaller cosa dovrebbe fare, lo passerà come char-array, molto probabilmente.

A parte questo, suggerirei di cambiare la DLL Delphi. Non è mai una buona cosa esporre qualcosa di specifico di Delphi in una DLL che deve essere utilizzata da client non Delphi. Rendi il parametro un array di PChar e dovresti andare bene.

Altri suggerimenti

Se questa è la tua DLL, riscriverei la funzione per accettare invece una matrice di stringhe. Evita di passare le classi come parametri DLL.

Oppure, se veramente vuoi usare un TStringList per qualche motivo, VCL.Net di Delphi può essere usato da qualsiasi linguaggio .Net.

Un vecchio esempio usando TIniFile: http://cc.codegear.com/Item/22691

L'esempio utilizza .Net 1.1 in Delphi 2005. Delphi 2006 e 2007 supportano .Net 2.0.

Se non controlli la DLL e non possono o non la modificano, puoi sempre scrivere il tuo wrapper Delphi in una DLL separata con parametri che siano più adatti alle diverse lingue.

Avere una classe come parametro di una funzione DLL è davvero una cattiva forma.

Non sono esattamente chiaro come usare delphi e C #. Sembra che tu abbia creato una DLL Win32 che desideri chiamare da C #. Al di fuori del corso devi usare PInvoke per questo.

Suggerirei di creare una DLL .NET utilizzando il codice sorgente poiché è disponibile il porting completo di VCL. Posso approfondire ulteriormente se lo desideri ....

In teoria, potresti fare qualcosa del genere usando i puntatori (lanciandoli come tipo C # IntPtr) invece di riferimenti a oggetti fortemente tipizzati (o magari avvolgendoli in qualche altro tipo per evitare di dover dichiarare blocchi non sicuri), ma la cattura essenziale è questa: il runtime Delphi deve essere il meccanismo per allocare e deallocare memoria per gli oggetti. A tal fine, è necessario dichiarare le funzioni nella DLL compilata da Delphi che invocano i costruttori e i distruttori per la classe TStringList, è necessario assicurarsi che la DLL Delphi utilizzi l'unità ShareMem e si deve assumersi la responsabilità di incrementare e decrementare il conteggio dei riferimenti per le tue AnsiString Delphi prima che lascino la DLL e dopo averla inserita, preferibilmente anche come funzioni esportate dalla tua DLL Delphi.

In breve, è un lotto di lavoro poiché è necessario destreggiarsi tra due gestori di memoria nello stesso processo (il CLR .NET e gli allocatori di Delphi) ed è necessario gestire entrambi manualmente la memoria e " sciocco " il gestore della memoria di Delphi e il runtime. C'è un motivo particolare per cui sei legato a questa configurazione? Potresti descrivere il problema che stai cercando di risolvere a un livello superiore?

Come ha detto Hemant Jangid, dovresti essere in grado di farlo facilmente compilando il tuo codice come dll .NET e quindi facendo riferimento a tale assembly nel tuo progetto c #.

Naturalmente, sarai in grado di farlo solo se la versione di Delphi che hai ha Delphi.NET.

Non so molto di c #, ma una tecnica che uso per trasportare liste di stringhe in contesti sta usando la proprietà .text per ottenere una stringa che rappresenta l'elenco, quindi assegnando quella proprietà sull'altro lato " ;.

Di solito è più facile ottenere una stringa sul muro che è un oggetto in piena regola.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top