Bueno Amigos, como cada domingo comienzan las Charlas de GNOME Hispano aqui en su canal #gnome-hispano, en la charla de hoy 12 de Enero, veremos el Sistema de Objetos de la Glib(GObject). Recuerden que las preguntas deben hacermelas a mi, estas pueden realizarse en el momento de lo deseen. Sin mas que agregar dejo con Uds. al Sr. Rodrigo Moya. hola el sistema de objetos de GLib que vamos a ver hoy se cre inicialmente para GTK la idea a la hora de crearlo era el traer, a un lenguaje no orientado a objetos las cosas ms interesantes de la POO como la herencia, el polimorfismo, etc en aquel entonces, C++ no era un lenguaje suficientemente estandarizado demasiado complejo y lioso en opinin de muchos desarrolladores y a la mayor parte de los desarrolladores de GNOME no les gustaba por tanto, se cre un sistema de objetos en GTK para ser usado en la creacin de los distintos widgets con el tiempo se vio que este sistema de objetos era realmente ltil, no slo para apps GUI si no para todo tpo de aplicaciones y por tanto, en GLib 2.0, se movi de GTK a GLib cuando se habla de sistema de objetos realmente el trmino es equivocado puesto que ms que un sistema de objetos es un sistema dinmico de creacin y comprobacin de tipos de datos es decir, en tiempo de ejecucin podemos crear nuevos tipos (entre ellos, clases) registrarlos en el sistema y hacerlos disponibles para el resto de la aplicacin esto permite, tambien en tiempo de ejecucin hacer comprobaciones de tipo de forma que si yo paso a una funcin un puntero no slo se comprueba que sea un puntero vlido si no que se comprueba su tipo para ver que es realmente lo que se espera esto soluciona muchos problemas a la hora de desarrollar en C donde no existe la comprobacin de tipos ms que en tiempo de compilacin (y ni eso muchas veces) el sistema de objetos/tipos de GLib no es m\x{00E1}s que una base de datos en la que se van registrando las distintas clases En esa base de datos, se almacenan todas las propiedades asociadas a cada tipo registrado, informaci\x{00F3}n tal como las funciones de inicializaci\x{00F3}n del tipo, el tipo base del que deriva, el nombre del tipo, etc, todo ello identificado por un identificador \x{00FA}nico, conocido como GType. as, cuando queremos registrar un tipo de datos nuevo tenemos que crear un nuevo identificador (GType) para el nuevo tipo y registrarlo en el sistema existen dos tipos de tipos que podemos registrar * tipos basados en clases (instanciables) * tipos fundamentales (no instanciables) los fundamentales no son ms que gint, gchar, etc aunque podemos registrar nuevos tipos fundamentales, si as se desea los tipos basados en clases son los que ms vereis en los programas GTK/GNOME son los basados en GObject, que es la clase base de todos los objetos para registrar un tipo de datos nuevo, primero hay que rellenar la estructura GTypeInfo: struct _GTypeInfo { /* interface types, classed types, instantiated types */ guint16 class_size; GBaseInitFunc base_init; GBaseFinalizeFunc base_finalize; /* classed types, instantiated types */ GClassInitFunc class_init; GClassFinalizeFunc class_finalize; gconstpointer class_data; /* instantiated types */ guint16 instance_size; guint16 n_preallocs; GInstanceInitFunc instance_init; /* value handling */ const GTypeValueTable *value_table; }; un ejemplo de uso: if (!type) { static GTypeInfo info = { sizeof (MyObjectClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) my_object_class_init, NULL, NULL, sizeof (MyObject), 0, (GInstanceInitFunc) my_object_init }; type = g_type_register_static (PARENT_TYPE, "MyObject", , 0); } vamos a comentar el ejemplo se trata de la creacin de una nueva clase llamada MyObject para ello, lo primero que hay que hacer es definir dos estructuras: typedef struct { GObject parent; } MyObject; typedef struct { GObjectClass parent_class; } MyObjectClass ; estas dos estructuras las crearemos para cada clase nueva que queramos crear la primera (MyObject) contendr los datos de cada instancia (una copia de la struct por cada instancia) de la clase la segunda (MyObjectClass) contiene los datos referente a todas las instancias de la clase y normalmente slo hay una copia de ella en el programa en ambas estructuras, el primer y nico campo es de tipo GObject* esta es la forma de especificar la herencia de clases en GLib mediante la inclusin, como primer campo de la estructura, del equivalente de la clase base en este caso, GObject una vez que tenemos estas estructuras hay que registrar la clase, que normalmente se hace en la funcion nombreclase_get_type: GType my_object_get_type (void) { static GType type = 0; if (!type) { static GTypeInfo info = { sizeof (MyObjectClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) my_object_class_init, NULL, NULL, sizeof (MyObject), 0, (GInstanceInitFunc) my_object_init }; type = g_type_register_static (PARENT_TYPE, "MyObject", , 0); } return type; } en esta funcin, simplemente se rellena la estructura de tipo GTypeInfo con la info de la nueva clase (ahora veremos todos los valores) y posteriormente se registra el tipo en el sistema de tipos de GLib mediasnte la funcin g_type_register_static que debera ser: type = g_type_register_static (G_TYPE_OBJECT, "MyObject", &info, 0); bien, vamos a ver la estructura: sizeof (MyObjectClass) -> especifica el tamao de la estructura de la clase (MyObjectClass) (GBaseInitFunc) my_object_init -> especifica la funcin de inicializacin de instancias de la clase perdn, lo ltimo est mal :-) (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, pasamos de estas dos lneas, de momento (GClassInitFunc) my_object_class_init -> especifica la funcin de inicializacin de la clase NULL, NULL, -> pasamos de ellos sizeof (MyObject) -> especifica el tamao de la estructura de instancia (MyObject) 0 -> pasamos (GInstanceInitFunc) my_object_init -> especifica la funcin de inicializacin de instancias de la clase como veis, es bastante sencillo despues de rellenar esta struct, simplemente se llama a g_type_register_static con: G_TYPE_OBJECT -> identificador de la clase base "MyObject" -> nombre de la clase &info -> struct recien rellenada 0 -> 0 :-) como veis, nos faltan dos cosas, que son las dos funciones my_object*_init : void my_object_class_init (MyObjectClass *klass); void my_object_init (MyObject *obj, MyObjectClass *klass); estas dos funciones son donde haremos todo el cdigo de inicializacin de la clase (my_object_class_init) y de cada una de las instancias que se creen (my_object_init) en _class_init normalmente se instalan los mtodos virtuales de la clase, etc que luego veremos, si nos da tiempo en _init, simplemente se inicializan los valores privados a cada una de las instancias void my_object_init (MyObject *obj, MyObjectClass *klass); 'obj' es un puntero a una nueva instancia que se acaba de crear mientras que 'klass' es un puntero a la estructura de clase, que normalmente, en esta funcin, no se usa por ejemplo, si necesitasemos almacenar valores privados en cada instancia de la clase MyObject declarariamos MyObject como: typedef struct { GObject obj; gpointer puntero_privado; gint entero_privado; } MyObject; en my_object_init hariamos: obj->puntero_privado = NULL; obj->entero_privado = 0; (o cualquier valor de inicio que quisieramos) hay alguna pregunta sobre esto, o paso a las seales y mtodos virtuales? creo que esta claro hasta el momento rodrigo.- bien como he comentado antes podemos simular lo que se conoce en POO como mtodos virtuales es decir podemos declarar una clase con una serie de mtodos y hacer distintas implementaciones de ese mtodo en las distintas clases derivadas de dicha clase esto se hace declarando, en la struct *Class los distintos mtodos virtuales, en forma de punteros a funciones por ejemplo typedef struct { GObjectClass parent_class; void (* metodo_1) (MyObject *obj, gint param1, gboolean param2); } MyObjectClass; podriamos hacer una implementacin de ese mtodo en MyObject: void my_object_metodo_1 (MyObject *obj, gint param1, gboolean param2) { ... } void my_object_class_init (MyObjectClass *klass) { klass->metodo_1 = my_object_metodo_1; } podriamos posteriormente crear nuevas clases basadas en MyObject que tuvieran su propia implementacion de ese mtodo simplemente, en su _class_init harian lo mismo aunque de forma distinta: typedef struct { MyObject obj; } MyObjectChild; typedef struct { MyObjectClass parent_class; } MyObjectChildClass; void my_object_child_class_init (MyObjectChildClass *klass) { MyObjectClass *object_class = (MyObjectClass *) klass; object_class->metodo_1 = my_object_child_metodo_1; } y por supuesto: void my_object_child_metodo_1 (MyObject *obj, gint param1, gboolean param2) { ... } bien, ahora vamos a ver como crear instancias de las clases que hemos definido es muy sencillo: un segundo, por favor paciencia, mientras esperamos a rodrigo.- mientras llega pueden pensar con calma sus preguntas. perdn bien deca: bien, ahora vamos a ver como crear instancias de las clases que hemos definido es muy sencillo: objeto = g_objecT_new (tipo_del_objeto, ...); normalmente, esto es: MyObject *obj; obj = g_object_new (my_object_get_type (), NULL); en get_type, si recordais registrabamos la clase en GLib (g_type_register_static) que devuelve un GType si mirais el codigo vereis que hay: static GType type = 0; if (!type) { se usa una variable esttica, que se inicializa a 0 de forma que slo se registra (if (!type)) la clase una sola vez ese GType identifica la clase y g_object_new, mediante ese id sabe cmo crear instancias de la clase vamos a ver un ejemplo ms claro de los mtodos virtuales vimos antes: en my_object_init hariamos: obj->puntero_privado = NULL; obj->entero_privado = 0; imaginaros que hacemos: obj->puntero_privado = g_malloc (2048); es decir, asignamos memoria para esa instancia de la clase como os podreis imaginar esta memoria, en algun momento, habr que liberarla GObject (la clase base), incluye un mtodo virtual que es finalize: void (* finalize) (GObject *obj) que podemos usar fcilmente en nuestras clases: void my_object_class_init (MyObjectClass *klass) { GObjectClass *object_class = (GobjectClass *) klass; object_class->finalize = my_object_finalize; } void my_object_finalize (GObject *obj) { MyObject *myobj = (MyObject *) obj; g_free (myobj->puntero_privado); } bien, creo que por hoy voy a parar para las preguntas y la semana que viene seguimos con seales, propiedades, etc alguna pregunta? ah, simplemente aadir, en relacin al polimorfismo que cada instancia de la clase MyObject puede ser tratada como un GObject de forma que podemos hacer: g_object_loquesea (myobj, ...); es decir, myobj es un MyObject, pero tambien es un GObject pues si no hay preguntas, terminamos pregunta rodrigo.- que si lo ultimo no necesita casts? mhz: lo necesita para compilar (GObject *) y, si quieres comprobacin de tipos: g_object_loquesea (GOBJECT (myobj), ...); no lo he comentado, pero con cada clase se suministran unas macros: #define GTK_TYPE_LABEL (gtk_label_get_type ()) #define GTK_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_LABEL, GtkLabel)) #define GTK_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_LABEL, GtkLabelClass)) #define GTK_IS_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_LABEL)) #define GTK_IS_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_LABEL)) #define GTK_LABEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_LABEL, GtkLabelClass)) que podemos usar para distintas cosas * GTK_TYPE_LABEL -> obtener el GType de la clase * GTK_LABEL -> hacer un casting con comprobacin de tipos en tiempo de ejecucin * GTK_LABEL_CLASS -> lo mismo pero para la *Class * GTK_IS_LABEL -> comprobacin de que realmente es del tipo GTK_TYPE_LABEL * GTK_IS_LABEL_CLASS -> lo mismo pero para la *Class * GTK_LABEL_GET_CLASS -> para obtener la *Class a partir de una instancia de la misma forma, para nuestra clase MyObject se podran suministrar esas mismas macros: #define MY_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_OBJECT_TYPE, MyObject)) ... eso en un .h esta claro.- o nadie escucha :-) alguna otra duda o consulta ? Creo que eso ha sido todo por hoy .- muchas gracias por su asistencia. --- rodrigo sets mode -m #gnome-hispano --- rodrigo gives channel operator status to gnomero y muchas gracias a ti rodrigo por esta charla magistral :-) plas plas plas [plas]* :-) super rodrigo !! **** ENDING LOGGING AT Mon Jan 13 20:06:08 2003