Programmare cellulari Symbian
UIQ in C++
=== appunti sparsi ===
Ultima revisione: 17 novembre 2006
(<new11-2>)
INDICE:
Per sviluppare programmi in C++ per cellulari Symbian UIQ è necessario scaricare un Source Development Kit (SDK), ad esempio dal sito SonyEricsson:
http://developer.sonyericsson.com/site/global/docstools/symbian/p_symbian.jsp
Oppure dal sito Symbian:
http://www.symbian.com/developer/sdks_uiq.asp
SonyEricsson p800, p900, p910 e Motorola a925/a1000 sono cellulari UIQ 2.x (il p800 e l'a925 sono 2.0, gli altri 2.1). Al momento con UIQ 3.0 c'e' solo il SonyEricsson p900. Bisognerà quindi scaricare l'SDK per UIQ 2.1 se si vuole scrivere un generico programma per UIQ. Se è specifico per il p800 servirà l'sdk per UIQ 2.0; se è per Motorola a1000 bisognerà scaricare anche l'SDK per l'a1000, che però da solo non può funzionare, in quanto costituisce un'aggiunta al generico SDK per UIQ, che quindi va comunque scaricato. Notare che esistono due tipi di SDK per UIQ 2.1: (winscw version) (225 MB) e (wins version) (168 MB) ; la prima serve per scrivere programmi usando l'IDE CodeWarrior, la seconda è per chi usa MS Visual Studio. Per chi usa... la linea di comando (!) dovrebbe essere indifferente, e forse preferibile il secondo, se non altro perche' si fa prima a scaricarlo.... ma a quanto pare se si vogliono far girare programmi in OPL sull'emulatore UIQ bisogna per forza usare il primo, per esempio. Quindi magari ci saranno anche altre differenze interessanti (dopotutto contiene 40 MB di roba in piu'); quindi, meglio usare la veriosne Winscw.
L'SDK per il Motorola a1000
L'SDK per a1000 risulta ancora in versione beta a un anno dall'uscita del cellulare.... Comunque. è scaricabile da motocoder.com (sito ufficiale) o da qui. Forse può essere utile anche l'SDK per l'a925 (UIQ 2.0), che sarà probabilmente più affidabile perché più testato. In ogni caso, motocoder.com è un ottimo punto di riferimento per chi vuole programmare l'a1000 (in C++, ma anche in J2ME; non supportano invece il PersonalJava, che probabilmente è implementato sull'a1000... per sbaglio, visto che non risulta dalle specifiche!), dal momento che hanno un ottimo servizio di assistenza per gli sviluppatori (ma bisogna ovviamente registrarsi al sito).
UIQ è il nome di una delle tante interfacce grafiche attraverso cui il sistema operativo Symbian dialoga con l'utente. Ci sono poi Series60 (cellulari senza touch-screen), Series80 e Series90 (Nokia communicators, con tastiere complete e senza touch screen) e altri.
CrezioInstallazione e configurazione dell'SDK
Dopo aver installato l'SDK per UIQ 7.0 (SonyEricsson p800 - Symbian 7.0) o UIQ 2.1 (SonyEricsson p910 - UIQ 2.1) (il che installa automaticamente anche PERL), supponendo di avere questi percorsi...
SDK UIQ 7.0: e:\symbian\uiq_70
PERL: e:\perl\bin
...ecco cosa bisogna fare per compilare uno degli esempi presenti nell'SDK:
Portarsi sul drive E:
Avviare un file batch, creato precedentemente, che contenga queste righe (ovviamente da adattare al proprio sistema):
SET
PATH=c:\windows;c:\windows\command\;e:\PERL\BIN;e:\Symbian\UIQ_70\epoc32\stubs\tools
set PERL5LIB=e:\Symbian\UIQ_70\epoc32\tools\perllib
set epocroot=
devices -remove @
devices -add E:\Symbian\UIQ_70 E:\Symbian\UIQ_70
@UIQ_70:com.symbian.UIQ
devices -setdefault @UIQ_70:com.symbian.UIQ
Notare l'uso della directory epoc32\stubs\tools anziche' epoc32\tools.
Notare la cancellazione della variabile di ambiente epocroot (non necessaria in quanto dopo si usa l'istruzione DEVICES)
Notare la rimozione di ogni altro device eventualmente già presente (devices -remove @)
Compilare un'applicazione già pronta
Portarsi dentro la cartella E:\Symbian\UIQ_70\UIQExamples\BasicApp (o in quella di un qualsiasi altro esempio sotto E:\Symbian\UIQ_70\UIQExamples\ ) e digitare:
bldmake bldfiles (la sintassi completa sarebbe bldmake bldfiles @UIQ_70:com.symbian.UIQ , cioè occorrerebbe specificare il device)
Questo genererà dei file intermedi; bisognerà poi digitare:
abld build armi urel (anche qui esiste una sintassi più completa: abld build thumb urel @UIQ_70:com.symbian.UIQ )
per compilare il programma per il telefono (si può usare anche abld build thumb urel) ; se si vuole invece compilare per l'emulatore, bisognerà scrivere abld build winscw udeb se si usa CodeWarrior, altrimenti abld build x udeb (vedi in questa stessa pagina spiegazioni su THUMB/ARMI e WINC/WINS/WINSCW). Specificando udeb piuttosto che urel, verrà aggiunto nel codice compilato del codice utile per effettuare il debugging.
<new11-2>Su
certi computer digitare
il comando abld
build
armi urel causa la comparsa di una
valanga di errori, al
punto che nemmeno facendo lo scrolling al contrario della finestra DOS
(su sistemi NT) si riesce a risalire al primo errore!! Cliccare poi col destro sul file, poi CREA COLLEGAMENTO, poi cliccare col destro sul collegamento e quindi su PROPRIETA'; nella finestra, scegliere la linguetta LAYOUT e immettere in ALTEZZA il numero di righe che la finestra DOS deve tenere in memoria. D'ora in poi, per compilare il progetto basterà fare doppio-click sul collegamento (che sarà utile rinominare in COMPILA.BAT) - Il secondo consiglio risolve il probelema a monte: l'errore NON si deve verificare! Il motivo per cui si verifica è un'incompatibilità del compilatore GCC con l'ambiente DOS, nel quale non è tollerato l'uso di spezzare una linea di codice in più parti. Questo accade in moltissimi dei file .h dell'SDK (di qui la miriade di errori), e se ne ha un esempio nel primo file "incriminato" dalla sequela di errori: ..\\..\\..\\..\\EPOC32\\INCLUDE\\e32std.h:3685:
`AType' was not declared in this scope Intorno alla riga 3685 del file e32std.h troviamo infatti: #define
DECLARE_ROM_ARRAY( AName, AData, AType ) \ L'errore è causato da quelle 3 " \ "... e dalla libreria sbagliata cygwin.dll in c:\windows\system32 sul vostro PC: eliminando il file si potrebbe risolvere il problema; ma siccome se il file sta lì ci sarà pure un motivo, meglio limitarsi ad aggirare il file, rinominadolo e mettendo al suo posto quello conetnuto in C:\Symbian\UIQ_70\epoc32\gcc\bin ) Fonti: |
Il risultato della compilazione, il file BasicApp.App, verrà memorizzato in E:\Symbian\UIQ_70\epoc32\release\thumb\urel (oppure E:\Symbian\UIQ_70\epoc32\release\armi\urel o E:\Symbian\UIQ_70\epoc32\release\winscw\urel , a seconda del comando usato prima ).
Copiando questo file (da thumb\urel o armi\urel, sicuramente NON da winscw\urel, in cui si trova il prgramma che funziona solo sull'emulatore) sul telefono, in c:\system\apps\BasicApp , l'applicazione dovrebbe risultare installata sul telefono ma non ancora avviabile: manca il file di risorse, che ha origine dal file BasicApp.rss presente nella cartella BasicApp, e che risulta in un file BasicApp.rsc salvato nella cartella E:\Symbian\UIQ_70\epoc32\data\z\system\APPS\BASICAPP.
Si potrebbe quindi riassumere il processo di compilazione di un programma c++ per Symbian in un file batch come questo:
(modificare opportunamente il nome dell'applicazione e la parte "E:\symbian\"):
e:\
cd E:\Symbian\UIQ_70\UIQExamples\BasicApp
bldmake bldfiles (bldmake
bldfiles
@UIQ_70:com.symbian.UIQ
se l'SDK di default è un altro)
abld build armi urel
(abld build
armi
urel @UIQ_70:com.symbian.UIQ se
l'SDK di default
è un altro)
copy
E:\Symbian\UIQ_70\epoc32\release\armi\urel\%1.app
.
copy
E:\Symbian\UIQ_70\epoc32\data\z\system\APPS\BASICAPP\%1.rsc
.
Le ultime due righe copiano nella directory corrente i file generati,
che
andranno copiati sul cellulare nella cartella
system\APPS\BASICAPP\.
In realtà i file da copiare alla fine potrebbero essere di
piu', di
meno o in altre posizioni, a seconda del progetto... Ma piu' o meno ci
siamo.
Per avviare l'emulatore:
epoc @UIQ_70:com.symbian.UIQ
o doppio click sul file EPOC.EXE desiderato:
Symbian\UIQ_21\epoc32\release\armi\urel\epoc.exe
Scrivere un'applicazione nuova partendo da un modello già pronto <new11-2>
Tramite questo script in Perl è
possibile creare
automaticamente lo scheletro di un'applicazione di base, che non fa
niente se non comparire sullo schermo e mettere a disposizione un menu
con l'unica voce EXIT. Sta allo sviluppatore poi riempirla come meglio
crede, per trasformarla nell'applicazione desiderata.
DOWNLOAD UIQ Wizard
Scrivere un'applicazione utilizzando un ambiente grafico per posizionare i controlli <new11-2>
Per scrivere un'applicazione per un ambiente grafico come Symbian (o Windows) è utile disporre di un ambiente che permetta di collocare, appunto, graficamente, i vari controlli dell'applicazione. Si può usare ad esempio OpenQUB oppure UBIQLIPSE. Il secondo è un plugin per Eclipse (che non sono riuscito ad installare...), il primo è un programma in Java, quindi per farlo funzionare dovete avere correttamente installato il Java Runtime Environment (JRE) sul vostro PC.
Ecco come appare l'ambiente OpenQUB:
Struttura di un'applicazione Symbian C++ per UIQ
All'interno della cartella \Symbian\UIQ_70 dell'SDK si trova una cartella chiamata UIQExamples (o simile) che contiene appunto programmi di esempio completi di sorgente, che possono essere modificati a piacimento per impratichirsi nell'ostica programmazione C++ Symbian. Dalla cartella dell'applicazione HelloWorld si evince qual è la struttura di una generica applicazione:
5 file di tipo .cpp (ognuno col suo corrispettivo .h): <new09-02>
NOME_Application.cpp - E' importante specificare in questo file l'UID dell'applicazione, che deve coincidere con quello specificato nel file .mmp
NOME_AppUi.cpp ("controller") <new09-02>
NOME_AppView.cpp ("view") <new09-02>
NOME_Document.cpp ("model") <new09-02>
NOME_Main.cpp
Un file NOME.rss - qui vengono definite le cosiddette RISORSE, come ad esempio le stringhe di testo che vengono utilizzate dal programma; il programma RCOMP.EXE, opportunamente richiamato tramite ABLD, si occupa di compilare i file .rss generando i corrispettivi binari .rsc, passando per file .rsg (che sono file di testo, di tipo "sorgente", anche se autogenerati).
Un file NOME.mmp
- qui viene specificata la struttura del progetto. Tra le altre cose,
è qui che vanno aggiunti i file .lib di cui fa uso
il programma. Per sapere quali file .lib contengono le
funzioni definite in un certo file .h,
basta leggere nella SDL - Symbian Developer Library
(quella generica Symbian o quella specifica UIQ), all'inizio della
pagina che descrive la funzione che vogliamo usare, a quali .lib si riferiscono
i var .h.
In questo file va anche specificato l'UID dell'applicazione: nella riga UID
sarà presente l'UID 0x100039CE, che identifica il tipo di
applicazione (DLL polimorfica), seguito da uno spazio e dall'UID
effettivo dell'applicazione. Per dettagli vedere la SDL (UIQ 2.1 SDK » Developer Library
» Tools and Utilities » Build tools guide
» How to build GUI applications » mmp project
specification); un esempio minimale di file .mmp potrebbe
essere il seguente:
<new09-02>
TARGET
HelloWorld.app
TARGETTYPE
app
UID
0x100039CE 0X10008ACE
VENDORID
0x70000001
TARGETPATH
system\apps\HelloWorld
SOURCEPATH
.
SOURCE
Hello.cpp
SOURCE
HelloApp.cpp
SOURCE
HelloDoc.cpp
SOURCE
HelloAppUi.cpp
SOURCE
HelloAppView.cpp
USERINCLUDE
.
SYSTEMINCLUDE
epoc32\include
RESOURCE
Hello.rss
LIBRARY
euser.lib apparc.lib cone.lib eikcore.lib
<new09-02>Per un'applicazione
standard, il "target" sarà di tipo .APP, ma esistono
svariati tipi
di target: librerie, recognizer, eseguibili...
Un file NOME.hrh - contiene l'elenco dei comandi (voci di menu, bottoni...) che l'applicazione può eseguire;
Un file NOME.h - qui vengono dichiarate le varie funzioni e variabili usate nei vari file .cpp, generalmente raggruppate, appunto, a seconda del file a cui si riferiscono;
Un file bld.inf - è il file usato dal comando BLDMAKE BLDFILES per generare il file ABLD.BAT, a sua volta usato per compilare i sorgenti.
Dalla compilazione dei file .cpp risultano dei file .o, che vengono poi collegati (link) tra loro in modo da formare, alla fine, il file .app, che non è un eseguibile vero e proprio, ma una libreria (DLL). E' tuttavia possibile specificare che il compilatore debba produrre un eseguibile vero e proprio, che avrà estensione .exe e sarà privo di interfaccia grafica. <new09-02>
Distribuzione di un'applicazione per Symbian (file .SIS)
Una volta certi che l'applicazione funziona, bisognerà creare un file SIS per distribuirla, dopo aver richiesto un UID univoco alla Symbian ([email protected]). Per creare il file sis, basta digitare
makesis nomefile.pkg
dove nomefile.pkg è un file di testo strutturato come segue (maggiori dettagli nella documentazione dell'SDK sul vostro hard disk: E:/Symbian/UIQ_70/Documentation/Packages/UIQ_70/sdl/ToolsAndUtilities/Installing-ref/PackageFileFormatReference.guide.html):
#{"BasicApp"},(0x12345678),7,0,0,TYPE=SA
Prima riga, obbligatoria; cambiare il nome dell'applicazione, e
sostituire
0x12345678 col suo UID
(0x101F617B), 2, 0, 0, {"UIQ20ProductID"}
Seconda riga, obbligatoria: il primo numero è il ProductID,
e deve
corrispondere con la strimga successiva.
"\Symbian\UIQ_70\epoc32\release\thumb\urel\BasicApp.app"-"!:\system\apps\basicapp\basicapp.app"
Copia il file da
\Symbian\UIQ_70\epoc32\release\thumb\urel\BasicApp.app
(sul PC) a
!:\system\apps\basicapp\basicapp.app
(sul cellulare; il "!" indica che il drive può
essere specificato
dall'utente).
"\Symbian\UIQ_70\epoc32\data\z\system\apps\BasicApp\BasicApp.rsc"-"!:\system\apps\basicapp\basicapp.rsc"
Analoga alla precedente.
Compilation
target -
dispositivo su
cui girerà un
programma
da
http://www.ent.mrt.ac.lk/dialog/Pages/News/Presentation1.pdf
Il Sistema Operativo Symbian gira nativamente su processori ARM, e supporta tre tipi di eseguibili ARM, chiamati Application Binary Interfaces (ABIs): ARM4, ARMI e THUMB
i programmi compilati per ARM4 utilizzano il set di istruzioni ARMv4, che è quello "di base". <new09-02>
i programmi compilati per THUMB utilizzano il set di istruzioni THUMB a 16 bit, sottoinsieme dell'ARMv4T, utilizzando l'istruzione BX (vedi sotto); con quetso set si ha un'ottimizzazione delle dinensioni dell'eseguibile. <new09-02>
i programmi compilati per ARMI utilizzano il set di istruzioni ARM, sottoinsieme di ARMv4T, utilizzando l'istruzione BX; con questo set si ha un'ottimizzazione della velocità di esecuzione. <new09-02>
L'istruzione BX permette di passare, nel corso dell'esecuzione del programma, dall'uno all'altro dei due subset di istruzioni ARM e THUMB.
Il codice del Sistema Operativo presente in ROM può essere stato compilato in uno qualunque dei 3 set di istruzioni, e dal momento che il subset ARMI è compatibile con tutti e tre, è consigliabile compilare codice per subset ARMI.
E' possibile anche compilare un programma affincé giri sull'emulatore anziché sul dispositivo reale, nel qual caso il target da specificare sarà WINS o WINSCW (vedi paragrafo Sigle degli emulatori)
Tra emulatore e dispositivo reale esiste una differenza nella risoluzione dei timer: sull'emulatore è di 1/10 di secondo, sul dispositivo è di 1/64, e occorre tenerlo presente nel testare i programmi sull'emulatore.
L'istruzione "semplice" abld build , senza ulteriori parametri, compila tutte le 8 varianti disponibili tra emulatore e dispositivo reale (ARM, THUMB, ARMI, WINS, in verisone UREL o UDEB) <new09-02>
WINC:
L'emulatore gira sotto WINdows;
E' usatto per sviluppare applicazioni di tipo "Console", cioè che non fanno uso di finestre;
Permette a programmi Windows di accedere ad applicazioni Symbian prive di interfaccia grafica;
Permette a programmi Windows di accedere a file dati Symbian utilizzando gli engine interni del S.O. Symbian;
Permette ai programmi dell'emulatore di accedere a qualunque directory del PC, non solo ai drive virtuali emulati come nell'emulatore WINS;
In generale (ma non sempre: le DLL derivate da Base non sono compatibili), una libreria per WINS puo' essere usata anche in WINC;
i componenti di WINC si trovano nella cartella epoc32\release\winc\variant\
Si avvia più rapidamente dell'emulatore WINS.
WINSCW:
L'emulatore gira sotto WINdows;
Le applicazioni che girano sull'emulatore girano in un Singolo Window-Process (cosa che non accade sul dispositivo reale), il che comporta la condivisione della memoria tra applicazioni diverse sull'emulatore, con conseguente "trasmissione" degli eventuali errori di gestione della memoria tra applicazioni diverse (cosa che non succede sul dispositivo reale);
L'emulatore può essere utilizzato insieme a strumenti di sviluppo esterni, come il Sistema di Sviluppo Integrato (IDE - Integrated Development Environment) chiamato CodeWarrior, o con VisualStudio.
WINS: Come WINSCW, ma progettato Per Microsoft Visual C++
Sigle:
STL - Standard Template Library
DLL - Dynamic Link Library
TLS - Thread Local Storage, usato per variabili globali (vedi nel resto del documento)
SDL - Symbian Developer Library
Ogni applicazione standard per Symbian, ovvero un file .APP, è in realtà una DLL, una Dynamic Link Library o (Libreria a Collegamento Dimamico); ossia, non è un programma indipendente, ma una raccolta di funzioni utilizzate da un altro programma (in questo caso, dal Sistema Operativo Symbian, immagino... TBD). Un'applicazione Symbian compilata invece per l'emulatore anziché per il dispositivo reale, è in realtà una DLL di Windows.
Il S.O. Symbian non permette l'uso di dati statici nelle DLL (quindi nei fille .APP), mentre Windows sì, perciò nelle applicazioni Symbian per il dispositivo reale non si posson usare dati statici (quindi variabili gobali), mentre in quelle per l'emulatore sì (perché è Windows a usare la libreria, non Symbian). (L'unica eccezione sono gli eseguibili Symbian (.exe), che non essendo librerie possono far uso di dati statici). Questo rende impossibile l'utilizzo di variabili globali; siccome però il loro uso in certi casi può tornare utile, Symbian consente in realtà di utilizzarle, ma solo all'interno di un thread: si parla di Thread Local Storage, TLS), cui si può accedere tramite la classe Dll. TLS è un semplice puntatore TAny*. (cfr. Symbian OS: From ANSI C/C++ To Symbian C++ v1.0) - se il link non funziona, cercare il titolo nel documento nella casella SEARCH di http://www.forum.nokia.com/). Questa limitazione non esiste per i file .EXE, in genere usati per scrivere Server.
Le classi sono divise in 4 tipi: T, C, R e M; ogni classe scritta dallo sviluppatore dovrà iniziare con la lettera corrispondente, per permetterne un'immediata classificazione "a vista" da parte di altri sviluppatori. Il significato delle iniziali è il seguente (cfr. Symbian OS: From ANSI C/C++ To Symbian C++ v1.0):
C (=cleanup): heap-allocated classes that are derived from a base class CBase;If a class owns some external data, then it must be a subclass (direct or indirect) of CBase and it's name will begin with C; this will be a C class. The CBase provides a virtual destructor, so even after casting to CBase * the right destructor will be called. Another nice feature of C classes is that it fills the data area with 0s, so you don't need to initialize variables to 0 or NULL (what is the most common case). Because the C classes will be pushed on the cleanup stack (which will be described later), C classes cannot be created on the stack - they must be created with the new operator (usually new(ELeave) as will be explaine
T (=type): value classes that do not own any external object; they cannot have pointers to data that is not owned by a different object. Such classes usually don't need a destructor. They can be created on the stack (i.e. as automatic variables) or inlined in a class
R (=resource): resource classes that contain handles to a real resource that is maintained elsewhere; the last commonly used prefix is R. These classes access to some external resources (e.g. files, sockets) and needs to be closed before exit. These classes don't have a common ancestor and there is no single closing function. The closing function is most often called Close(), sometimes Dispose() or Delete().
M (=mixin): interface classes that define abstract protocol definitions that are implemented by derived classes. Somehow analogical to T and C classes are the structs and classes in C#. Symbian uses also classes which are analogical to Java or C# interfaces. They are prefixed with M and can contain only pure virtual functions. Symbian discourages multiple inheritance unless all the superclasses except at most one are M classes.
Notare che benché le classi T possano essere create sullo stack, questa non è una buona idea. Sul dispositivo reale lo stack ha dimensioni molto ridotte (8KB per default) e alcune classi T occupano molto spazio (TFileName, ad esempio, occupa più di 512 byte). Dal momento che l'emulatore utilizza lo stack di Windows NT, che può arrivare fino a 8 MEGAbyte, non ci si accorgerà di eventuali problemi di memoria finche' non si proverà il programma sul dispositivo reale. Al contrario, sul dispositivo reale, come detto, lo stack è molto ridotto; le classi più "voluminose" andranno memorizzate nell'heap; in questo caso, però, la memoria allocata per la classe dovrà poi essere liberata manualmente, al contrario di quanto accade con le classi sullo stack, la cui memoria viene deallocata automaticamente all'uscita dalla classe.
Le classi vengono create nello heap tramite new.
Le classi statiche
non hanno nessun prefisso e iniziano con una lettera
maiuscola.
Non
esistono eccezioni come
in C++ "classico", sotto Symbian si usano le
leaves, che possono
essere generate direttamente da una
funzione (col metodo User::Leave(), equivalente
al Throw
del C++), o da una struttura di TRAPPING
(implementata tramite
TRAP e TRAPD, vedi
più avanti). Si fa quindi un "trapping leaves" invece che
un "catching exceptions". Ogni metodo che prevede un "leave"
deve avere
un nome che finisce per "L"(cfr.
Symbian
OS: From ANSI C/C++ To Symbian C++ v1.0),
è così pure
i metodi che lo chiamano. Tuttavia non tutti i metodi devono
necessariamente
effettuare il trapping, che è comunque
effettuuato da Symbian
OS.
Symbian OS gestisce in modo particolare le "exceptions" del
processore,
tramite la classe RThread: se una di queste exceptions
non
è catturata dal programma, il Sistema la
catturerà emettendo
un panic con codice KERN EXEC 3.
Oltre ai leaves esistono infatti i panics,
che non possono
essere intercettati e causano l'interruzione immediata del thread. Si
può
generare un panic con User::Panic.
TRAP-TRAPD:
Per intercettare un "leave" occorre che la funzione che lo genera sia
gestita in un modo particolare; supponendo che FunzioneL() sia la
funzione che può generare un leave (bisogna quindi
aggiungere una L alla fine del nome), avremo:
void
FunzioneL()
{
CExample* myExample = new CExample;
if (!myExample) User::Leave(KErrNoMemory);
// leave used in place of return to indicate an error
// do something
myExample->iInt = 5;
testConsole.Printf(_LIT("Value of iInt is
%d.\n"),myExample->iInt);
// delete
delete myExample;
}
Per intercettare quando un leave proviene da questa funzione, bisogna chiamare la funzione tramite un TRAP:
TInt
E32Main()
{
testConsole.Title(); //Scrive il
titolo
testConsole.Start(_LIT("Example")); // start a
new "test"
//
Variabile associata al "leave"
TInt r=0;
//
Chiama la funzione: se esce con un "leave",
//
il codice del "leave" e' messo in r.
TRAP(r,FunzioneL());
//
Processa la variabile che potrebbe contenere il codice del leave:
if (r)
testConsole.Printf(_LIT("Errore: codice leave=%d"),
r);
testConsole.End(); // finisce
testConsole.Close(); // chiude
return KErrNone; // ritorna
}
Quando si ha un leave, la funzione ritorna subito, senza dare il tempo di liberare eventuale memoria allocata; questo causerebbe un "memory leak" (spreco di memoria), che non è accettabile in un dispositivo con memoria limitata come un cellulare. La gestione dei leave è quindi strettamente connessa con la gestione della memoria (cleanup).
Esiste infatti uno stack appositamente dedicato all'allocazione e deallocazione di memoria per le risorse richieste dal programma; questo perché, come detto, quando una funzione termina con un leave non dà tempo di liberare la memoria coi metodi tradizionali; esempio:
CDemo*
demo = new CDemo;
DangerousOperationL();
delete demo;
Se la funzione esce con un leave, l'istruzione delete non verrà mai eseguita! Ecco quindi il modo corretto con cui va chiamata una funzione:
CDemo*
demo = new CDemo();
CleanupStack:: PushL(demo); // Allocazione sullo stack
DangerousOperationL();
CleanupStack:: PopAndDestroy()
//
deallocazione: se il flusso di programma non arriva
// qui (a
causa di un leave), ci
pensa il sistema a
//
cancellare il primo elemento
dallo stack con un
//pop
& destroy.
Bisogna
quindi ricordarsi di mettere sul Cleanup Stack qualunque oggetto
"pericoloso" creato tramite New o NewL. NewLC crea invece direttamente
nel Cleanup Stack.
Bisogna
fare attenzione
però a non cancellare l'oggeto sbagliato: se per esempio
l'oggetto viene messo in un array, esso dovrà essere
deallocato
dal cleanup dell'array, e se si tentasse un PopAndDestroy
DOPO che l'array ha deallocato, si deallocherebbe l'oggetto sbagliato!
Se però per fare il pop si usa pop(object),
nella versione di debug ci sarà un PANIC se si tenta di
deallocare un oggetto che non corrisponde a quello sullo stack (cosa
che non succede nella versione "release").
Il Cleanup Stack può essere usato anche per chiudere le risorse: se si mette una risorsa sul CS con CleanupClosePushL, il successivo PopAndDestroy(), oltre a deallocarla, la chiuderà anche.
Al posto delle stringhe si usano i descrittori, che sostituiscono le stringhe null-terminated, gli array di byte e gli array di puntatori.
Le applicazioni
Symbian sono strutturate per lavorare con server
di sistema, ai quali richiedono/inviano
dati tramite le API
di sistema. I dati possono essere scambiati in modo sincrono o
asincrono.
Il Symbian OS è organizzato secondo una struttura
Client/Server: il
kernel del S.O. è minimo, la maggior
parte dei servizi sono
forniti da server che a esso si collegano e a cui
si collegano le
varie applicazioni. I server forniscono delle classi che rendono
trasparente
l'utilizzo del sistema client-server.
I file di risorsa sono obbligatori, perché servono a definire l'interfaccia visibile all'utente. Sono utili anche per facilitare la traduzione dei programmi in lingue diverse (localization), e perché possono contenere stringhe utilizzate dal programma, che così vengono caricate in memoria solo quando serve.
I vari controlli disponibili in una GUI derivano tutti dalla classe CCoeControl. Esiste un IDE gratuito chiamato Open QUB che permette di creare interfacce grafiche usando il mouse anziché scrivendo codice a mano (non l'ho ancora provato, ma se funziona è decisamente un tool molto utile).
Le applicazioni Symbian sono in genere a thread singolo; possono anche essere multi-thread, ma tale pratica è sconsigliata.
Symbian OS è un S.O. con multitasking non-preemptive; gli eventi vengono pianificati (scheduled) da Active Scheduler e gestiti (handled) da Active Objects.
Ogni applicazione per S.O. Symbian deve avere un identificativo univoco, chiamato UID. Per lo sviluppo si possono usare a piacere tutti gli UID compresi tra 0x01000000 e 0x0fffffff, ma per applicazioni da distribuire al pubblico occore farsi dare un UID univoco dalla Symbian ([email protected]). L'utilizzo di un UID "sbagliato" causa il classico errore "NOT FOUND" all'avvio dell'applicazione. L'UID dell'applicazione non va confuso con il ProductID, un altro UID che specifica su quale variante di Symbian girerà un certo programma.
Scrivere un'applicazione Symbian OS completamente in C anziché C++ è difficile o quasi impossibile, ma se si hanno dei vecchi sorgenti C da "riutilizzare", si possono eventualmente implementare come server, in quanto i server supportano le variabili globali, presenti nel linguaggio C. Si tratta quindi solo di aggiungere del codice per gestire i messaggi tra server e applicazioni. Il risultato finale sarà comunque un'applicazione piuttosto lenta.
Nei programmi per Symbian non si possono usare percorsi relativi per i file, bisogna sempre specificare il drive (o usare la speciale implementazione Symbian di STDLIB).
Lo sviulppo di applicazioni per WINC è analogo a quello per WINS:
creare un file .mmp per specificare il prgetto;
avviare makmake per generare un make-file per linea di comando, o un file di progetto per Microsoft Visual C++;
per compilazioni da linea di comando, usare nmake per utilizzare il make-file di linea di comando.
Emulatore
Compilando un programma per l'emulatore WINS/WINSCW anziche' per il dispositivo reale, i files ottenuti verranno memorizzati in percorsi differenti.
Applicazioni con interfaccia grafica: viene generato un file con suffisso .APP, e a seconda se la compilazione è stata fatta a scopo di debug o release, e per emulatore WINS o WINSCW, il file verra memorizzato in percorsi diversi:
epoc32\release\winscw\udeb\z\system\apps\program-name
epoc32\release\winscw\urel\z\system\apps\program-name
Applicazioni con interfaccia grafica possono avere o non avere un file AIF associato, che ne definisce, tra le altre cose, l'icona. In mancanza di tale file, viene usata un'icona di default, ma l'applicazione non potrà aprire nuovi file (??tbc??) è non può essere embedded.
Per avviare il file .APP ottenuto occorre lanciare rispettivamente uno di questi eseguibili, che avvierà l'emulatore adatto da cui avviare l'applicazione:
epoc32\release\wins\udeb\epoc.exe
epoc32\release\wins\urel\epoc.exe
epoc32\release\winscw\udeb\epoc.exe
epoc32\release\winscw\urel\epoc.exe
Applicazioni a linea di comando ("console"):
I programmi compilati per WINC vengono messi in \epoc32\release\winc\variant\
Sui dispositivi reali, le applicazioni
prive di interfaccia grafica hanno
suffisso .EXE; tuttavia, esse non possono essere avviate sugli
emulatori.
Quando però un'applicazione console
viene compilata per un
emulatore, essa viene dotata di codice aggiuntivo che permette di
avviarla
direttamente da Windows (da una finestra DOS o da Esplora Risorse). Per
sviluppare applicazioni per console, bisogna compilarle per WINC,
ottenendo
un file .EXE. Questo file riceve il controllo da E32Main(),
che
non ha parametri, quindi per leggere eventuali parametri della linea di
comando
bisogna usare una API Symbian: la cosa migliore è usare la
classe
CCommandLineArguments. Si può scrivere
anche un'eseguibile
.EXE per Windows invece che per console, che farà
riferimento a librerie
compilate e testate sotto WINC per accedere a dati Symbian. (cfr.
The
WINC build target in Build tools guide). Gli UID non hanno
alcuna importanza
quando si compila per WINC. .Un eseguibile .EXE per WINC va avviato
specificando
non il solo nome del file, ma l'intero percorso.
Per compilare un'applicazione come .EXE, ocorre un file MMP contenente
le
righe TARGETTYPE exe
e UID 0;
un esempio di file MMP per un EXE è il seguente:
TARGET HelloWorld.exe
TARGETTYPE exe
UID 0
SOURCEPATH .
SOURCE HelloWorld.cpp
USERINCLUDE .
USERINCLUDE ..\CommonFramework
SYSTEMINCLUDE \Epoc32\include
LIBRARY euser.lib
Programmi server:
Programmi che fungono da server sono compilati come EXE, ma non possono essere avviati sugli emulatori, per i quali vanno compilati come DLL
Librerie:
Vengono compilate con suffisso .DLL, e in genere messe per default nelle stesse directory degli EXE, ma il percorso puo' venir cambiato dallo sviluppatore.
<new09>Il p800 supporta i set di istruzioni ARMI e THUMB: il primo è a 32 bit, il secondo a 16 bit. In entrambi i set ci sono istruzioni che consentono di passare dall'uno all'altro modo.
I programmi THUMB sono piu' piccoli ma piu' lenti.
<new09>Un programma compilato in RAM ha questa struttura:
E32 executable image header (0x7C bytes) | |
Code section | Text section (code and constant data) |
Import table | |
Export table | |
Data section (initialised data) | |
Import section | |
Code relocation section | |
Data relocation section |
<new09>Compilato per la ROM, invece, ha questa struttura:
E32 ROM image header (0x64 bytes)s | |
Code section | Text section (code and constant data) |
Data section (initialised data) | |
Export table | |
DLL reference table |
<new09>(rif. http://www.virusbtn.com/virusbulletin/archive/2005/09/vb200509-symbian-os.dkb)
<new09>Il codice eseguibile inizia all'inicio della Text Section.
Links:
Ricerca tra le FAQ della Symbian: http://www3.symbian.com/faq.nsf/SearchAll?OpenForm
SDK per SonyEricsson P800/P900/P910: http://developer.sonyericsson.com/site/global/docstools/symbian/p_symbian.jsp
Codici d'errore Symbian OS: http://www.newlc.com/article.php3?id_article=117
Far creare un LOGFILE a un'applicazione: http://www.newlc.com/article.php3?id_article=131
Far mostrare versione estesa di un errore all'emulatore (e forse anche al cellulare stesso): http://www.newlc.com/article.php3?id_article=150
Sorgenti gratuiti per Symbian (c++ e Java)
Compilare senza IDE:
http://www3.symbian.com/faq.nsf/0/E961EA6C04EA6BF080256EDD0055D063?OpenDocument
http://www.newlc.com/article.php3?id_article=497
http://www.newlc.com/article.php3?id_article=463
http://pf128.krakow.sdi.tpnet.pl/symbdev/
(cambiato in http://www.mikolaj.zalewski.pl/symbdev/)
Tutorial Symbian c++: http://www.pocketvnc.com/tutorials/symbian/symbian.aspx
Symbian Example (sito con molte chiacchiere per s60, ma utile): http://symbianexample.com/projectwizard
Appunti
di programmazione in ambiente Symbian
C++
Usare
Carbide.c++
Importare
un progetto in Carbide.c++
da un file .MMP
Compilare
un eseguibile Symbian .exe multiplatform
Appunti di programmazione PersonalJava
Compilare
un'applicazione
PersonalJava, creare i file .APP, .AIF e .TXT per
lanciarla, e installarla sull'emulatore.
Appunti di programmazione
Java Midlet