Ritorno al...managed
Dopo essere partiti dal codice managed nella prima parte, attraversato i confini di .NET nella seconda ed essersi immersi nel codice nativo nella terza parte, vediamo in questa sessione conclusiva come ripassare al codice gestito restituendo i risultati ottenuti dalla DLL scritta in C++. Ricordo che dalla funzione della DLL ci aspettiamo una chiamata ad un metotdo di callback passandogli un intero e una stringa. Il metodo di callback che raccoglie i parametri dalla parte unmanaged si chiama "ReceivedCall" che tra non molto vedremo nel dettaglio. Prima di analizzare questo metodo, vorrei sottoporre all'attenzione di tutti il meccanismo tramite il quale si va ad aggiornare l'interfaccia grafica, inserendo l'integer e la stringa in due textbox.
La classe ControlInvoker
Durante alcuni giri su google, ho trovato degli esempi su QuickStart della Microsoft in cui veniva esposta questa classe estremamente utile per un sacco di motivi. Vi consiglio di guardarla e, nel caso utilizzaste dei meccanismi di multithreading, di utilizzarla per ottenere un miglior codice. Come viene chiaramente spiegato nel QuickStart Tutorial, il .NET Compact Framework non offre il supporto per le chiamate asincrone BeginInvoke e EndInvoke, ma sopratturro non supporta il passaggio dei parametri nelle chiamate sincrone effettuate con Invoke. Questo sarebbe estremamente limitativo nel nostro caso in quanto il metodo di callback ha bisogno di invocare un metodo (relativo al thread della Form) per passargli l'intero e la stringa che ha ricevuto dalla DLL e far così aggiornare la GUI. Ci tengo a ricordare che il metodo di clallback NON può aggiornare lui stesso la GUI poichè si violerebbe un precetto fondamentale di meccanismo di "Apartment" che impone che solo il thread che possiede gli oggetti grafici (quali textbox, bottoni o qualunque cosa si trovi nella interfaccia grafica) possa aggiornarli, altrimenti dobbiamo passare tramite Invoke. C'è però l'handicap del passaggio di parametri non supportato. La classe ControlInvoker nasce proprio per aggirare questa limitazione. Vediamo com'è fatta questa classe:
La prima cosa che deve essere fatta (ed è quello che facciamo nel codice della nostra applicazione) è quello di creare un'istanza della classa ControlInvoker passandogli l'istanza della Form (quindi this) di cui vogliamo invocare i metodi. Quando all'interno del Managed Listener Thread vogliamo invocare un metodo per aggiornare la GUI effettueremo questa chiamata:
a definizione del delegate MethodCallInvoker è questa:
public delegate void MethodCallInvoker(object[] o);
Quindi, tramite questa definizione di delegate, stiamo passando un metodo, "UpdateCallArriving", e i suoi parametri all'istanza controlInvoker, la quale sarà lei a pensare a nascondere il metodo con i suoi parametri ed effettuare la corretta invocazione. il metodo invocato avrà quindi la seguente firma ed il seguente comportamento:
Finalmente i risultati provenienti dalla parte unmanaged vengono aggiornati sulla interfaccia grafica.
Conclusioni
In queste quattro sessioni abbiamo visto molti aspetti interessanti che riguardano i meccanismi di integrazione tra mondo managed e mondo unmanaged all'interno dei dispositivi mobile. Vi sottolineo l'importanza del marshalling tra i due mondi che viene risolto tramite Platform Invoke, ma che non sempre appare liscio come ci aspettiamo, anche con dati apparentemente banali come le stringhe. Come tradizione vi lascio tutto il codice di cui potete fare il download facendo attenzione che è stato complato per Windows Mobile 6. Se non avete l'SDK per Windows Mobile 6 o lo scaricate dal sito Microsoft oppure riportate pari pari lo stesso codice in un progetto per Windows Mobile 5 e ricompilate. Nessuna modifica è necessaria, nell'un o o nell'altro caso, alla DLL nativa. l'unica cosa a cui dovete fare attenzione è che in fase di deploy coincidano le directory in cui vengono memorizzati sul device sia il .exe sia la DLL, poichè al omento dell'invocazione della load Library si presuppone che siano nella stessa cartella. Rimango comunque a in attesa di vostri eventali commenti e/o suggerimenti migliorativi.
sv.