| Ste Dev |
P/INVOKE
Sto cercando di interoperare con una DLL win32 che implementava un protocollo proprietario di comunicazione seriale.
Ho creato la seguente interfaccia: interface IProtocolloBase { bool Connetti(int com, int baudRate, char parity, int dataBit, int stopBit, int veicolo, int dispositivo, uint nTraceTime); void Sconnetti(); bool ScritturaRandom(Int32[] pdwAddresses, char[] pchBuffer, uint size, uint sizeOfBasicType); bool Reset(); } Ho definito poi una classe che implemeta questa interfaccia: public class Protocollo98 : IDisposable, IProtocolloBase { #region Win32API [DllImport("serprt98.dll")] public static extern bool SPConnect(int COM, int baudRate, char parity, int dataBit, int stopBit, int veicolo, int dispositivo, uint traceTime); [DllImport("serprt98.dll")] public static extern void SPDisconnect(); // questo è il prototipo scritto in Visual C++ // BOOL SPWriteRandom(LPDWORD pdwAddresses, LPCSTR pchBuffer, // UINT nSize, UINT nSizeofBasicType) [DllImport("serprt98.dll")] public static extern bool SPWriteRandom(Int32[] pdwAddresses, char[] pchBuffer, uint size, uint sizeOfBasicType); [DllImport("serprt98.dll")] public static extern bool SPResetCPU(); #endregion public Protocollo98() { } ~Protocollo98() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if(disposing) { // vengono liberate le risorse relative ai managed objects } // vengono liberate le risorse relative agli unmanaged objects Sconnetti(); } public bool Connetti(int com, int baudRate, char parity, int dataBit, int stopBit, int veicolo, int dispositivo, uint traceTime) { return SPConnect(com, baudRate, parity, dataBit, stopBit, veicolo, dispositivo, traceTime); } public void Sconnetti() { SPDisconnect(); } public bool ScritturaRandom(Int32[] pdwAddresses, char[] pchBuffer, uint size, uint sizeOfBasicType) { return SPWriteRandom(pdwAddresses, pchBuffer, size, sizeOfBasicType); } public bool Reset() { return SPResetCPU(); } } Chi mi da un occhio se ho implentato correttamente i wrapper ? Sopratutto quello chiamato ScritturaRandom che in Visual C++ lo avevo scritto così; BOOL SPWriteRandom(LPDWORD pdwAddresses, LPCSTR pchBuffer, UINT nSize, UINT nSizeofBasicType) pdwAddresses memorizzava un array di indirizzi di variabili che andavo a crivere via seriale. pchBuffer era un buffer di unsigned char che conteneva i valori da spedire via seriali associati agli indirizzi precedenti. GRAZIE |
| Raffaele Rialdi |
Re: P/INVOKE
> // questo è il prototipo scritto in Visual C++
> // BOOL SPWriteRandom(LPDWORD pdwAddresses, LPCSTR pchBuffer, > // UINT nSize, UINT nSizeofBasicType) > [DllImport("serprt98.dll")] > public static extern bool SPWriteRandom(Int32[] pdwAddresses, char[] pchBuffer, > uint size, uint sizeOfBasicType); A occhio direi: [DllImport("serprt98.dll", CharSet=CharSet.Auto)] public static extern bool SPWriteRandom(ref uint pdwAddresses, [in,out] StringBuilder pchBuffer, uint size, uint sizeOfBasicType); LPDWORD è un puntatore ad una dword e quindi un ref ad un uint. LPCSTR può essere string se è solo in ricezione ma se è anche in uscita deve essere uno StringBuilder perchè il buffer interno della string è immutabile. il resto è ok. C'è una bella tabella in msdn nell'articolo "Platform Invocation Services" Raffaele |
| Ste Dev |
Re: P/INVOKE
Grazie 1000 Raffaele,
per passare alla mia DLL un array di indirizzi mi hai suggerito ref uint :pdwAddresses In questo modo riesco a spedire alla mia DLL più indirizzi del tipo: 0x00000001 0x00000002 ..... Ho un dubbio su StringBuilder pchBuffer quello che dovrei utlizzare per spedire alla mia dll un array di valori: a me servirebbe spedire un array di unsigned char. Posso utilizzare la StringBuilder per questo scopo ? Grazie per il chiarimento. |
| Raffaele Rialdi |
Re: P/INVOKE
> In questo modo riesco a spedire alla mia DLL più indirizzi del tipo:
> 0x00000001 > 0x00000002 Non avavo capito che ce ne fossero molti. Se ce n'è più di uno probabilmente non ti funziona Ma con quale parametro sai quanti indirizzi ci sono nell'array? Potrebbe essere necessario usare "MarshalAs" (guarda msdn perchè la questione è più complessa) .net infatti deve riuscire a capire quanto è lungo l'array. > Ho un dubbio su StringBuilder pchBuffer quello che dovrei utlizzare per spedire alla mia > dll un array di valori: > a me servirebbe spedire un array di unsigned char. Posso utilizzare la StringBuilder per > questo scopo ? > Grazie per il chiarimento. Si, dopo tutto una stringa è un array di byte che terminano con null. Il vantaggio di trattarli come stringa viene dal fatto che sai già come capire dove finisce l'array. Raffaele |
| Ste Dev |
Re: P/INVOKE
Ricordi il prototipo della mia funzione:
public static extern bool SPWriteRandom(Int32[] pdwAddresses, char[] pchBuffer, uint size, uint sizeOfBasicType); Il parametro SIZE mi determina quanto è lungo l'array pwdAddress. Hai qualche idea ? Devo usare MarshasAs ? |
| Corrado Cavalli |
Re: P/INVOKE
Visto che la DLL riceve l'indirizzo di memoria di partenza dell'array ha bisogno ovviamente di conoscere la lunghezza quindi basta che passi semplicemente il numero di elementi contenuti,non e' necessario MarshalAs
HTH Corrado |
| Ste Dev |
Re: P/INVOKE
Ti ringrazio per la risposta ora mi mettero un po a studiare l'interoperablilità ! Ma giusto per avere un'idea: quando o meglio in quali situazione uso MarshalAs ?
|
| Raffaele Rialdi |
Re: P/INVOKE
Concordo con Corrado se l'array è di lunghezza fissa.
Se è invece di lunghezza variabile (così mi sembrava) devi usare MarshalAs, specificando la proprietà SizeParamIndex che dice qual'è il parametro della funzione che indica la lunghezza dell'array (nel tuo caso size). MarshalAs permette inoltre di specificare manualmente la mappatura tra il tipo nativo (win32) e il tipo .net quando la mappatura automatica non è soddisfacente. (Su msdn ci sono un po' di esempi). Raffaele |
| Corrado Cavalli |
Re: P/INVOKE
Quando devi dettagliare al condice unmanaged come trattare il parametro che gli passi, in particolar modo quando il parametro puo' essere passato in modi diversi (vedi ad esempio le stringhe che possono essere passate sia ANSI che UNICODE)
MarshalAs e' anche necessario quando devi passare una struttura che ha dei fields di tipo stringa a lunghezza fissa. HTH Corrado |
| Ste Dev |
Re: P/INVOKE
GRAZIE 1000.
Scusa non c'entra nulla, al forum dell'11 marzo ho visto Andrea usare Visio per rappresentare gli oggetti del sito UGI. Io ho due versioni di Visio: Visio 2002 professional e Visio for Enterprise Architect. Mi chiedo qual'è piu appropriato installare ? Quale usava Andrea durante il suo intervento ? GRAZIE e scusa per questo FUORI ARGOMENTO |
| Corrado Cavalli |
Re: P/INVOKE
Credo che la persona piu adatta per rispondere sia Andrea, comunque se ben ricordo Visio EE e' qualla che si integra direttamente in VS quindi forse la piu' adatta.
Corrado |
| Andrea Saltarello |
Re: P/INVOKE
> Quale usava Andrea durante il suo intervento ?
Ciao "Ste"... Come ti ha giustamente detto Corrado, stavo usando la ver "Enterprise Architect" > GRAZIE e scusa per questo FUORI ARGOMENTO prego :-) .A |
| Ste Dev |
Re: P/INVOKE
Impossibile chiederti una bozza del documento Visio che hai fatto vedere durante l'incontro dell'11 marzo che mi sembra riguardava proprio il sito UGI ?
|
| Andrea Saltarello |
Re: P/INVOKE
hai posta...
.A |
| Ste Dev |
Re: P/INVOKE (x Andrea S.)
Ti rigrazio
vmister@tiscali.it. Infatti mi piacerebbe vedere come avevi progettato ad alto livello le classi astratte TemplateContenuto e TemplateContenutoCategorizzato ! Un po di design del software fa bene ogni tanto !!! Ciao e grazie 1000 |