Glib es una libreria de C orientada a la portabilidad. Es decir,si Glib esta portada para Windows (por ejemplo), un programa desarrollado en Glib en Linux puede ser compilado en Windows.
Antes de tirarnos de lleno a Gtk+, primero hay que hacer un par de programitas en Glib.
2.1 Tipos de datos
Al igual que la libreria estandar de C, Glib posee sus propios tipos de datos estándar.
Los siguientes tipos de datos estan definidos por Glib:
- gint9, guint8, gint16, gint32, guint32, gint64, guint64
- gboolean.
- gchar, gshort, gint, gfloat, gdouble
- gpointer, gconstpointer.
2.2 Un pequeño programa
Para poder entender Glib con mas claridad, usemos un pequeño pedazo de código:
#include <glib.h>/* primero.c */int main (int argc, char * argv[]){ gint numero; gchar letra; gchar *cadena; numero=1; letra='p'; cadena = "12345"; /* no recomendado, usar g_string_new */ g_print("Hola mundo\n"); g_print("Mi primer programa en Glib\n"); g_print("El valor de numero es %d\n",numero); g_print("El valor de letra es %s\n",&letra); g_print("El valor de cadena es %s\n", cadena); return 0;}
Para compilar este programa
$ gcc `glib-config --cflags` `glib-config --libs` -o primero primero.c
Para ejecutar
$ ./primero
La salida de este programa seria
Hola mundoMi primer programa en GlibEl valor de numero es 1El valor de letra es pEl valor de cadena es 12345
g_print() reemplaza a printf() de C. Posee exactamente el mismo formato. En este caso, se imprimen los tipos de datos gint (entero) y gchar.
Si se dan cuenta, el uso de punteros es indispensable en programación en Glib. Como ejercicio para el lector queda repasar un buen libro de C (sugerido en la seccion de “impresos”).
2.3 Hubiera sido tan fácil...
...hacer mis tareas de programación si hubiera usado Glib. Absolutamente todos los rebuscados tipos de datos necesarios para una tarea de programación han sido implementados en Glib.
Por ejemplo...
Listas ligadas
La estrella de mis tareas de programación!
Una lista ligada es una estructura que contiene un dato (que generalmente es puntero a algo, como un gchar) y un puntero que apunta al siguiente elemento de la lista.
Se puede definir en C como
struct _GSList{ gpointer data; GSList *next;} typedef struct _GSList GSList;
Existen en Glib una serie de primitivas para el manejo de listas.
Veamos un ejemplo para entender estas funciones:
#include <glib.h>/* segundo.c */int main (int argc, char * argv[]){
creando una nueva lista vacia GSList *milista = NULL; gchar nombre; nombre = "tux"; agregar un elemento a la lista (encolar) milista = g_slist_append(milista, nombre);
o mas rapido aun milista = g_slist_append(milista, "gtk"); agregar un elemento al principio de la lista milista = g_slist_prepend(milista, "gdk");
agregar elemento en la segunda posicion (0 es la primera) milista = g_slist_insert(milista, "papa_roach", 1); revertir el orden de la lista milista = g_slist_reverse(milista);
imprimiendo el largo de la lista g_print("El largo de la lista es %d\n", g_slist_length(milista)); encontrando el n elemento de la lista g_print("El tercer elemento de la lista es %s\n", g_slist_nth_data(milista,2)); g_slist_free(milista); return 0;}
Se compila exactamente igual que el ejemplo anterior.
Listas doblemente ligadas
Parecidas a las listas ligadas, con la diferencia que existe un puntero que apunta al elemento anterior.
La definicion es la siguiente
struct _GList{ gpointer data; GList *next; GList *prev;} typedef struct _GList GList;
Ahora, un “sencillo” ejemplo
#include <glib.h>
tercero.cint main (int argc, char *argv[]){ GList *milista=NULL; GList *aux1=NULL; agregando un elemento a la lista milista = g_list_append (milista, "elemento1");
agregando otro elemento a la lista milista = g_list_append(milista, "elemento2"); agregando otro elemento, pero al principio milista = g_list_insert(milista, "elemento0", 0);
en orden inverso milista = g_list_reverse(milista); g_print("El largo de la lista es %d\n", g_list_length(milista)); g_print("El segundo elemento de la lista es %s", g_list_nth_data(milista, 1)); apuntar al segundo elemento de la lista aux1=g_list_nth(milista, 1);
liberando las listas g_list_free(milista); g_list_free(aux1); return 0;}
Árboles
La otra estrella de las tareas de programación!
Los árboles son las estructuras de datos más odiadas y más útiles en programación. Ordenamiento? Árboles. Compresión? Árboles. Los ejemplos sobran...
Son bastante mas complicados de manipular que los otros tipos de datos anteriores.
Para crear un arbol, se usa la funcion g_tree_new(), que devuelve un puntero a un GTree. Para esto, se debe pasar como parametro una funcion de comparacion, de modo que el arbol pueda ajustarse automaticamente y proporcionar un rapido acceso a los datos.
Por ejemplo, una funcion piñufla de comparacion seria:
gint comparar_arbol(gpointer data1, gpointer data2){ return (strcmp(data1, data2));}
Ahora, un ejemplo...
#include <glib.h> cuarto.cgint comparar_arbol(gpointer data1, gpointer data2){ return (strcmp(data1, data2));} gint recorrer (gpointer key, gpointer value, gpointer data){
funcion para recorrer el arbol char *sKey= key; char *sValue = value; g_print("Key : %s - Value : %s\n",sKey, sValue); return FALSE;} int main (int argc, char *argv[]){ GTree *miarbol; miarbol=g_tree_new((GCompareFunc) comparar_arbol); ahora, a insertar elementos
g_tree_insert requiere 3 parametros: 1- el arbol
2- un gpointer (key) 3- un gpointer (data) g_tree_insert(miarbol, "52x", "cdrom"); g_tree_insert(miarbol, "24x", "grabador"); g_tree_insert(miarbol, "optico", "mouse"); g_tree_insert(miarbol, "austral", "cerveza"); g_tree_insert(miarbol, "spencer", "libro");
el otro clavo: recorrer el arbol hay tres maneras : en orden, pre orden y post orden
para hacerlo, se puede implementar una funcion que se ejecuta cada vez que se recorra el arbol
en este caso, recorrer() en orden g_tree_traverse (miarbol, recorrer, G_IN_ORDER, NULL); g_print("\n");
pre orden g_tree_traverse (miarbol, recorrer, G_PRE_ORDER, NULL); g_print("\n"); post orden g_tree_traverse (miarbol, recorrer, G_POST_ORDER, NULL);
liberar g_tree_destroy(miarbol);}
Fuera del espectro del documento esta explicar la diferencia entre recorrer el árbol en orden, pre y post orden. Pero imagino que aquellos que ya hayan sido torturados con ramos similares a Estructuras de Datos ya sufrieron implementando estas mismas funciones...
3. Lo que se viene
Aunque haya sido una lata repasar Glib antes de la programación en Gtk+, era necesario explicar la base de la programación grafica usando Glib para los tipos de datos.
Próximo artículo, unos pocos hola mundo en Gtk+.