Didattica C: Primi passi con le gtk

Arriva un momento nella vita di un uomo in cui si abbandona l’essenziale per abbracciare il sofisticato ed il frivolo. Questo è anche ciò che accade nella vita di un programmatore: arriva il giorno in cui si abbandona la riga di comando per iniziare ad usare le finestre tanto amate dall’utente comune!

Bene! Dopo questo preambolo in stile zen possiamo iniziare il cammino per studiare come dare vita al nostro codice C grazie alle gtk.

E’ doveroso, prima di cominciare, spiegare cosa sono le gtk.

GTK+ (acronimo di GIMP ToolKit) è il nome di un insieme di strumenti grafici, basati sulla libreria libgtk, che permette di programmare e creare interfacce grafiche con lo steso stile di quelle che normalmente vediamo in ambiente Gnome. Qualora vorreste iniziare a programmare con tali librerie bisogna prima soddisfare le dipendenze installando libgtk2.0-dev presente nei repository di tutte le distro.

Ora possiamo iniziare a vedere un semplicissimo codice che genera una finestra standard 200×200 pixel.


#include

int main (int argc, char *argv[])
{
GtkWidget *window;

gtk_init(&argc, &argv);

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_show(window);

gtk_main();

return 0;
}

Iniziamo con l’analizzare riga per riga il codice appena scritto.

Per prima cosa bisogna importare mediante #include il file contenente le funzioni e le strutture su cui si basano le gtk+; il file gtk/gtk.h, infatti, deve essere presente in ogni software che basa la propria interfaccia su questa libreria.

Mediante la dichiarazione di gtkWidget si ottiene un elemento di tipo finestra (window appunto) che potrà essere successivamente manipolato attraverso i suoi metodi.

Con gtk_init(&argc, &argv) si inizializzano tutti i parametri mediante alcuni argomenti da riga di comando che sono noti a tutti i programmi gtk. E’ possibile, infatti, passare da terminale alcuni parametri che si potrebbero definire standard e che sono uguali per qualsiasi software che sfrutti queste librerie. Essi sono: –display, –debug-level, –no-xshm, –sync, –show-events e –no-show-event.
Il nostro programma al suo avvio andrà alla ricerca di questi parametri e qualora ne incontri qualcuno, lo legge, lo usa, lo elimina dall’array argv[] e decrementa argc. In questo modo alla fine di questo processo sarà possibile analizzare gli argomenti eventualmente passati dall’utente come si faceva prima di usare le gtk.

La riga window = gtk_window_new(GTK_WINDOW_TOPLEVEL) crea la finestra sfruttando una inizializzazione simile a quella presente in linguaggi come il C++.

Gtk_widget_show(window) si limita a mostrare la finestra appena creata.

Dopo le inizializzazioni dei nostri elementi, si incontra la chiamata a gtk_main(). Tale funzione non fa altro che dirci che il codice a finito di creare l’interfaccia e che è in attesa che in X accada qualche evento da gestire (ad esempio la pressione di un tasto della tastiera o un doppio click del mouse).

Infine si pone un return 0 come si era abbituati per restiuire l’intero dichiarato all’inizio del nostro main se l’applicazione si chiude senza problemi.

Questo è solo un semplice esempio. Per quanto stupido possa essere esso contiene le basi per capire il funzionamento iniziale di queste librerie. Si vdrà più avanti qualche esempio più “corposo”.

Alla prossima 🙂

Didattica C: Passaggio parametri da linea di comando

Quando si opera in ambito shell solitamente si creano programmi capaci di accettare diversi parametri che serviranno per impostare o modificare diverse componenti del software stesso. Vediamo come scrivere del codice in C per abilitare e gestire argomenti passati al programma da linea di comando.

Iniziamo col vedere il codice utile a svolgere tale scopo:

int main(int argc, char* argv[])

Quello che si vede è il classico main presente, necessariamente, in ogni programma scritto in C. Chi ha dimestichezza con il linguaggio in questione noterà che tra le parentesi che normalmente si lasciano vuote sono presenti due nuove variabili, argc ed argv[].

int Argc è un intero che contiene il numero di parametri passati al programma mediante la riga di comando. Si noti che se i parametri passati sono n, argc varrà n+1 poichè esso conteggia anche il programma stesso.

char* Argv[] (o equivalentemente **argv) è un array di tipo puntatore a char (carattere) e contiene le stringhe equivalenti ai vari parametri. Ogni elemento del vettore infatti contiene il parametro salvato come stringa. Da notare che in argv[0] è salvato il nome del programma stesso.

Vediamo un esempio.

Prendiamo un semplice codice C che legge i dati passati da riga di comando r gli stampa nuovamente nel terminale.

int main(int argc, char* argv[])

{
int i;

//-- leggiamo ogni parametro presente in linea di comando
for ( i=0 ; i!=argc ; i++ ){
printf("%s\n", argv[i]);
}

return 0;

}

Il codice in questione è molto semplice. Esso, grazie ad un ciclo for, controlla di volta ogni parametro passato.

Compilando il programma e scrivendo nel terminale:

./programma cane gatto topo

Il terminale restituirà:

./programma
cane
gatto
topo

Infatti eseguendo il ciclo for si vede che per i=0 si ha argv[0] ovvero il nome del programma stesso, per i=1 si ha il primo parametro cioè cane per i=2 si ha il secondo parametro e così via.

Come si vede l’uso dei parametri è abbastanza facile e permette una versatilità del software abbastanza potente pur non avendo a disposizione una GUI con la quale impostare i valori.

Didattica C/C++: Creare un’interruzione in secondi

Alle volte può succedere di aver bisogno di interrompere il regolare svolgimento di un codice scritto in C per un tempo di n secondi. Le strade da intraprendere in questo caso possono essere diverse: si potrebbe controllare , ad esempio l’ora di sistema con un ciclo ed uscirne solo quando sono passati i secondi desiderati. Questa soluzione, per quanto logica possa essere, porta problemi in termini di uso di CPU. E’ più facile, pertanto, ricorrere ad una semplicissima funziona del linguaggio C contenuta nella libreria unistd.h. La funzione in questione è sleep che ha il seguente prototipo:

unsigned int sleep(unsigner int second)

dove second è il tempo (espresso in secondi) per cui si vuole che il processo sia fermo.

Ovviamente la praticità di questa funzione è evidente ma proprio l’altro giorno mentre utilizzavo questo metodo mi sono imbattuto in un errore.
Il programma in questione era qualcosa del tipo:

# include
# include

int main()
{
int i;

for (i=0;i<=4;i++)
{
printf("stringa");
sleep(1);
}

return 0;
}

Nel terminale infatti avrei dovuto vedere stampata una parola ogni secondo per un tempo di 4 secondi; quando però lanciavo via terminale il mio programma compilato notavo che le mie parole venivano stampate tutte insieme senza tenere conto dell’attesa di sleep. Dov’era allora il problema? Bene il problema risiedeva in dei problemi di bufferizzazione dell’ouput standard. Il problema è facilmente arginabile ponendo un fflush(stdout) dopo lo sleep; fflush infatti forza la scrittura dei dati presenti nel buffer. Pertanto, molto semplicemente il codice diventa:

# include
# include

int main()
{
int i;

for (i=0;i<=4;i++)
{
printf("stringa");
sleep(1);
fflush(stdout);
}

return 0;
}

Spero di essere stato utile…..alla prossima!