GNOME y CORBA
Introducción
Este artículo está basado en el libro de Mathieu Lacage y Dirk-Jan C. Binnema titulado "GNOME y CORBA". Se hará menos hincapié en CORBA de lo que se hace en el libro, y nos centraremos en el uso de CORBA dentro de GNOME, en concreto en cómo CORBA lográ que todas las aplicaciones de GNOME se puedan comunicar entre ellas y, gracias a Bonobo, incluso una aplicación puede contener a otra y controlarla.
Este ejemplo práctico del uso de CORBA en GNOME cubre casi todos los aspectos de la arquitectura CORBA y abre puertas a una metodología de desarrollo nueva, abierta y multiplataforma, gracias a las interfaces IDL que definen todo el sistema. En cierto modo se va dejando el mundo de las cabeceras de C para pasar al mundo de las interfaces IDL, que son en la mayoría de los casos mucho más fáciles de entender.
Para desarrollar con GNOME vamos a necesitar lo más nuevo en cuestión de software, ya que hasta hace muy poco este desarrollo era complejo y las interfaces de programación cambiaban de forma incompatible. Por ello se recomienda al lector que intente seguir el artículo desde un distribución como Linux Mandrake 6.1.
CORBA en GNOME
Ya comentamos en anteriores entregas de la serie la exitencia de ORBit, una implementación de CORBA 2.2 muy ligera y desarrollada en C. Esta implementación se desarrolló en exclusiva para GNOME ya que las necesidades de GNOME eran muy específicas: necesitaba una implementación de CORBA reducida y muy rápida ya que se incluye dentro de la mayoría de aplicaciones de GNOME. Cuando se comenzó a desarrollar GNOME se disponía de MICO pero su lentitud a la hora de ser utilizado dentro de las aplicaciones y la cantidad de recursos que necesitaba, forzaron a los desarrolladores de GNOME, muchos de ellos con máquinas poco potentes, a abondonar su uso y desarrollar su propia implementación.
El principal problema de ORBit a la hora de empezar a manejarlo es que utiliza C orientado a objetos, al igual que lo hace GTK, y la sintaxis inicialmente es un tanto engorrosa. Esta sensación inicial se vence tras los primeros programas, y ORBit incluye facilidades para ahorrarnos el tener que teclear más de los estríctamente necesario, siendo capaz de generar código de ejemplo al que lo único que le falta es rellenar la implementación de las funciones de las interfaces IDL.
Aparte de las funcionalidades del propio ORBit, se ha desarrollado una librería para facilitar el uso de CORBA dentro de GNOME, conocida como libgnorba y que describimos en el siguiente apartado.
La librería de CORBA de GNOME: libgnorba
Para facilitar el uso de CORBA dentro de GNOME se ha desarrollado una librería que intenta encapsular la mayor parte posible de CORBA, con el objetivo de facilitar la vida del desarrollador. Esta librería es gnorba y recubre principalmente las llamadas de inicialización de CORBA que se encargan de inicializar el ORB y de resolver las referencias a los servicios predefinidos dentro del ORB.
Inicialización de CORBA en GNOME
Quizás este es un buen momento para que el lector acuda a la anterior entrega de este curso con el objetivo de no perderse. Vamos a recordar estos conceptos de inicialización:
- CORBA_ORB_init: esta función era la encargada de inicializar el ORB tanto en el cliente como en el servidor, y debía de ser llamada antes de empezar a utilizar CORBA.
- CORBA_ORB_resolve_initial_services: dentro de CORBA exisen servicios para facilitar la vida del desarrollador y la potencia de la plataforma. En la anterior entrega cubrimos con detalle el servicio de nombres. Algunos de estos servicios son tan importantes que el uso de CORBA sin ellos es complejo y mucho menos potente, por lo que se incluyen por defecto dentro del ORB, y el ORB conoce las referencias a estos servicios. Para acceder a estas referencia de servicios ya registrados dentro del ORB utilizamos "CORBA_ORB_resolve_initial_services" pasando como parámetro a esta función el servicio que queramos utilizar. Recordemos que esta función ya la hemos utilizado para obtener la referencia al servidor de nombres y al POA raíz (RootPOA) en ejemplos anteriores de esta serie de CORBA.
Unas reglas inciales del uso de C orientado a objetos dentro de CORBA podrían ser: ORB es un objeto de la clase CORBA y la sintaxis para llamar a funciones de este objeto es CORBA_ORB_nombre_funcion. Cuando queramos aplicar una función sobre un objeto este objeto se le pasará como parámetro a la función. Y para el tratamiento de las excepciones habrá que pasar en toda llamada a función CORBA un parámetro en dónde se guararán las posibles excepciones. De cualquier forma en los ejemplos tendremos tiempo de analizar en concreto esta sintaxis.
Prosigamos con la librería gnorba de GNOME. Cuando queríamos que un servidor CORBA se quedara a la espera de los clientes, finalizabamos al servidor en un bucle infinito (CORBA_ORB_run()) desde el que se trataban todos los accesos al servidor CORBA.
La librería GTK, con la que se crean las interfaces gráficas en GNOME, también acaba sus programas en un bucle final, en el que se reciben los eventos del usuario sobre la interfaz gráfica (pulsaciones de un botón, arrastre de una ventana ...).
Está claro pues que un programa que utilice GNOME debería de terminar en dos bucles infinitos, algo que no es posible. La librería gnorba se encarga de encapsular estos dos bucles e integrar el bucle de CORBA dentro del de GTK en la llamada a la función gnome_CORBA_init. Veamos un ejemplo de su uso:
#include
#include
#include
int main (int argc, char **argv)
{
CORBA_ORB orb;
CORBA_Environment ev;
CORBA_exception_init (&ev);
orb = gnome_CORBA_init ("ejemplo de inicialización de ORB y GTK",
"v 1.0 Barrapunto - acs",
&argc,
argv,
GNORBA_INIT_SERVER_FUNC,
&ev);
return 0;
}
Vemos que se utiliza la librería orbit, gnorba y gnome la cual a su vez utiliza GTK. La llamada a la función gnome_CORBA_init nos devuelve el ORB con el que vamos a trabajar a partir de este momento.
Para poder compilar los ejemplos de este artículo es indispensable tener instalada una distribución con un GNOME actualizado y con los paquetes de desarrollo instalados. Para compilar estos ejemplos se va a utilizar Mandrake 6.1. Para compilar este pequeño programa se puede utilizar la línea:
gcc `gnome-config --cflags gnorba` ej1.c
Aquí vemos una utilidad muy potente a la hora de compilar que nos evita el uso de complejos Makefiles. Con gnome-config podemos obtener los distintos flags necesarios a la hora de compilar y enlazar con las distintas librerías de gnome. En este caso, como sólo compilamos y no enlazamos, le decimos que nos dé los flags necesarios para poder compilar un programa que utiliza la librería gnorba, cuyo resultado es: -I/usr/include -DNEED_GNOMESUPPORT_H -I/usr/lib/gnome-libs/include -I/usr/lib/glib/include. Las librerías GTK y GLIB también nos proporcionan utilidades similares.
Servidor de Nombres en GNOME
Como ya vimos en anteriores capítulos el servidor de nombres CORBA nos permite acceder a las referencias a los objetos por medio de un nombre. Es una especie de DNS pero para los IOR ( identificador de objeto interoperable). Un problema que tiene ORBit es que no se puede acceder actualmente al servidor de nombres a través de la función del ORB CORBA_ORB_resolve_initial_reference. Y un segundo problema es cómo se arranca el servidor de nombres CORBA de forma automática cuando se necesite.
De nuevo libgnorba viene en nuestro auxilio y se encarga de resolver ambos problemas. Utilizando la llamada gnome_name_service_get obtenemos la referencia al servidor de nombres en el caso de que el servidor esté arrancado. En el caso de que no lo esté, esta llamada lo arranca de forma automática y nos devuelve el IOR del servidor de nombres arrancado.
Por lo tanto el programador es liberado de ambas labores y para el casi transparente el cómo se gestiona el servidor de nombres. El sabe que a esta referencia puede pedirle que le devuelva la IOR de otros objetos a partir de un nombre.
GOAD: Demonio de Activación de Objetos en GNOME
Dentro de libgnorba también tenemos unos API que nos permiten obtener un listado de todos los servidores CORBA disponibles en el sistema, y podemos activarlos y desactivarlo en función de nuestras necesidades.
Con la propia librería viene una utilidad conocida como goad-browser que permite acceder al conjunto de servidores registrados dentro del sistema. En la siguiente figura vemos la información que nos proporciona dicha utilidad.
En la primera columna vemos el identificador del servidor, si está activo o no lo está (desde aquí lo podemos activar) y el identificador de la interfaz IDL que describe al servidor. Por ejemplo, si activamos el control_center nos aparecerá la ventana que nos permite configurar todo el entorno gnome. En cierto modo el goad-browser lo podemos ver como un lanzador de aplicaciones.
Pero la verdadera potencia está en la API de acceso a GOAD, muy sencilla. De ella presentamos las dos funciones principales de la misma (dentro de gnorba.h está la API completa).
| Nombre función |
Uso de función |
| goad_server_list_get |
Lista de servidores registrados en GOAD |
| goad_server_activate |
Activa un servidor CORBA de GOAD |
Cuando desarrollemos un programa en CORBA, si necesitamos la funcionalidad de otro que esté presente en el sistema y registrado dentro de GOAD, podremos activarlo a través de esta interfaz de forma muy sencilla. Y además, podremos acceder a todas la funcionalidad que exporte por su interfaz IDL, tal y como se haría en cualquier servidor CORBA en otro entorno. De esta forma empezamos a ver la potencia y sencillez que aporta CORBA a un entorno gráfico como GNOME, y esto aún es sólo el principio, la verdadera potencia llegará con el mundo de los componentes y Bonobo.
Si una vez que hemos desarrollado nuestro programa creemos que puede ser útil registrarlo como un servidor CORBA dentro de GOAD, lo debemos de dar de alta dentro del directorio /etc/CORBA/servers (en Linux Mandrake 6.1). Para ello añadimos en este directorio un nuevo fichero con el nombre nombre_servidor.gnorba. Por ejemplo, si nos fijamos de nuevo en el Centro de Control el fichero que lo describe es gnomecc.gnorba y su contenido es:
[control_center]
type=exe
repo_id=IDL:GNOME/control_center:1.0
description=GNOME Control Center
location_info=gnomecc
El fichero como vemos es autodescriptivo: gnomecc es un ejecutable cuya interfaz IDL es IDL:GNOME/control_center:1.0.
Conclusiones de libgnorba
Gracias a esta librería podemos evitar temas siempre espinosos y de poco interés para nuestra aplicación final: la inicialización de CORBA, la activación y acceso al servidor de nombres de CORBA y el control de registro de servidores CORBA y su activación. El lector que tenga más presente POA posiblemente piense que el GOAD es algo que se podría implementar con POA y los servant manager. Es cierto, pero los desarrolladores de GNOME entienden que esta solución es más sencilla. Quizás como no tienen el problema de la portabilidad entre ORBs, este tipo de aspectos los prefieren solucionar "ad-hoc" (a medida) para su caso concreto.
El escritorio GNOME
Ha llegado el momento de ver cómo todas las piezas del sistema se combinan entre sí. Y son todas esta piezas coordinadas lo que se conoce como el escritorio de GNOME, un sistema en el que varias aplicaciones se unen entre sí con el fin de dar un conjunto de funcionalidades de forma gráfica al usuario del sistema.
La mayoría de las definiciones de las interfaces de las aplicaciones GNOME se encuentran en el directorio /usr/share/idl.
Entre las interfaces IDL que se definen destacan:
- desktop-viewer.idl: interfaz que implementan todas las aplicaciones capaces de visualizar texto.
- desktop-editor.idl: interfaz que implementan las aplicaciones que quieren sr consideredas editores de texto dentro del entorno.
- gnome-unknown.idl: interfaz COM Unknown básica dentro del modelo de componentes Bonobo.
- GnomeObject.idl: interfaz común para todos los objetos Bonobo.
- gnome-factory.idl: interfaz sencilla para objetos factoría.
- gnome-panel.idl: interfaz del panel de GNOME, compleja y amplia.
- help-browser.idl: interfaz al sistema de ayuda de GNOME.
Por ejemplo, si quisieramos crear un entorno de desarrollo para GNOME, lo que hacemos es crear el núcleo que interacciona con el editor de textos, el compilador, el depurador etc. a través de las respectivas interfaces IDL de cada módulo. Nuestro entorno a partir de este desarrollo podrá trabajar con diferentes editores y compiladores de diferentes lenguajes sin mas que cambiar el objeto al que accedemos para que haga cada uno de los papeles. Es la flexibilidad llevada a su máxima expresión.
Desde cualquier aplicación nuestra dentro del entorno de GNOME podemos acceder a todos los servicios que nos ofrecen estas interfaces. No hay que olvidar que el tener las interfaces IDL nos permite poder acceder a los objetos que las implementan. Vemos que la unión entre todos los elementos de GNOME se consigue en gran medida gracias a CORBA.
Para que el lector se pueda hacer una idea de cómo están definidas estas interfaces en el siguiente cuadro se puede ver la de help-browser.idl.
Interfaz help-browser.idl en GNOME
module help_browser {
interface simple_browser {
void fetch_url(in string URL); // muestra URL en el navegador actual
simple_browser show_url (in string URL); // abre navegador y muestra URL
};
};
El lector, si ha seguido la serie, no tendrá ningún problema en entender con detalle la interfaz. Recordemos que si quisieramos acceder a la interfaz de ayuda, a partir de este IDL y utilizando el compilador IDL de ORBit (orbit-idl), generamos los cabos (en lenguaje C) en este caso, los cuales incluimos en nuestro programa y ya podemos utilizar el sistema de ayuda integrado de GNOME. Para localizar el objeto que implementa esta interfaz, utilizamos el servidor de nombres y buscamos la IOR del objeto cuyo nombre sea gnome-help-browser. Una vez que tenemos la referencia al objeto ya sabemos lo sencillo que es utilizar el objeto con simples llamadas sobre esta referencia.
Realmente todo este proceso se simplifica algo gracias a las librerías de GNOME, pero las ideas que están detrás siguen siendo las mismas.