<-- Capítulo

Índice del tutor de Delphi
© Copyright 1998
por David Martínez.

Todos los derechos reservados

Capítulo -->

Capitulo 9.1. Interfases COM en Delphi

Ahora que sabemos cómo funciona una interfase y como se implementa en Object Pascal, veamos cómo funcionan las interfases COM (y DCOM) en específico.

COM es un transporte para interfases. La conveniencia de COM es que viene con todas las copias de Windows en el planeta, así que no hay que preocuparse de instalar librerías con su sistema. La parte inconveniente es que si usted utiliza COM, su programa solo puede hablar con máquinas que corran Windows (hay un esfuerzo para implementar la librería COM en Unix, pero no ha tenido éxito técnico o político).

ActiveX es simplemente un conjunto de interfases COM y utilerías relacionadas que, cuando usted implementa, permiten que su producto sea utilizado en lenguajes de programación como componente visual. Todos los componentes de Visual Basic son ActiveX, y cualquier componente de Delphi puede implementar un ActiveX también. Esto quiere decir que cualquier componente visual que usted haga en Delphi puede ser utilizado en programas de Visual Basic. A su vez, Delphi puede utilizar cualquier componente ActiveX.

La diferencia entre un Componente de ActiveX y un componente de Delphi normal (.pas) es que ActiveX es independiente del lenguaje, pero los componentes de Delphi son mucho más compactos y no le requiere redistribuir binarios ajenos a su programa.

Ejecutables en Windows

La implementación de una interfase COM en Delphi puede vivir en cualquier archivo de 32 bits que Windows pueda ejecutar. Estos archivos pueden ser ejecutables, Librerías DLL o Librerías OCX. Hay ciertos detalles en cuanto a lo que es soportado en cada uno de estos tipos de implementación, como hilos de ejecución o capacidad de funcionar como un control de ActiveX. Un solo ejecutable puede implementar todas sus interfases, o puede usted granularizar en diferentes servicios como más convenga a su caso en particular.

Como Windows Maneja COM

Para poder instanciar una interfase, la computadora necesita saber en qué ejecutable vive esta interfase, y además necesita saber algunos otros detalles acerca de su ejecución, como puntero de entrada a cada una de las interfases (dentro del ejecutable), permiso de usuario con los cuales el ejecutable va a funcionar, etcétera. Toda esta información es guardada por el registro de Windows.

Lo primero que necesitamos para una interfase es no confundirla con otra. Para esto se utilizan los llamados GUIDs, o Globally Unique IDentifiers. Estos identificadores son una especie de número de serie aleatorio de 128 bits generado utilizando una función llamada CoCreateGUID. La función está escrita de manera tal que se le garantiza que éste numero nunca será repetido. Esto es importante porque el GUID es el identificador que la computadora utilizará para nuestra interfase en todas las computadoras de todo el mundo, y no queremos que nuestras interfases se confundan con las de otra persona. Por ejemplo, en todo el planeta, el siguiente GUID identifica al Active Desktop de Internet Explorer:

{FBF23B40-E3F0-101B-8488-00AA003E56F8}

Las interfases en Windows vienen en "paquetes de interfaces" llamados CoClasses. Un CoClass es una clase que implementa una o más interfaces. En COM, todas las funciones que manejan interfases de manera abstracta comienzan con el preidentificador "Co". De esta manera sabemos que esta función es una función que puede ser aplicada a cualquier CoClass, no obstante los particulares de la misma.

Tómese unos cuantos minutos para examinar el registro de Windows con el programa REGEDIT. Usted podrá observar que uno de los folders de "raíz" se llama HKEY_CLASSES_ROOT. Este folder contiene toda la información de todas las interfases. Su nombre, su identificador único, sus permisos, etcétera. Windows utiliza COM durante su operación diaria, así que usted encontrará los GUIDs de interfases de Windows, Borland, y todas sus aplicaciones junto con sus propias interfases.

Utilizar regedit para ver sus interfases puede resultar complicado. Microsoft tiene funciones para averiguar información acerca de las interfases sin tener que accesar el registro, y se reservan el derecho de cambiar el formato del registro. Así que dentro de lo posible, procure que su programa utilice las funciones del Windows API para averiguar información acerca de las interfases en vez de usar el registro.

Hay un programa muy útil llamado OleView en el sitio de Microsoft que nos proporciona toda la información pertinente a las interfases COM instaladas en la computadora.

TODO: Find link to OleView.exe

Instanciando Interfases

Los programas en Windows pueden ser muy diferentes. ¿Cómo sabe Windows cómo instanciar una interfase? Cuando el programa inicializa (antes de comenzar a ejecutar), Delphi crea por nosotros una "Fabrica de Objetos" (Class Factory). Una fábrica de objetos es un objeto concreto que genera objetos de la clase cada vez que Windows decide que un programa cliente ha solicitado un puntero de interfase. Si usted utiliza las capacidades de RAD de Delphi, rara vez se tendrá que preocupar acerca de esto, pero es importante que tenga en mente como funciona para resolver algunos problemas que no son obvios. Por ejemplo, si por algún motivo su objeto nunca inicializa y usted nota que el procedimiento create nunca ejecuta (y el objeto está registrado), el problema puede ser que la fábrica de objetos nunca está siendo creada. Si no hay fábrica de Objetos, Windows no puede crear una CoClass.

En Object Pascal, una fábrica de objetos se instancía en la sección initialization de la unidad donde vive el objeto. Por ejemplo, un objeto recién creado utilizando los Wizards de Delphi tiene la siguiente sección de implementación en la unidad donde usted implementará el objeto:


implementation

uses ComServ;

initialization
  TAutoObjectFactory.Create(ComServer, TClientes, Class_Clientes,
    ciMultiInstance, tmApartment);
end.

TAutoObjectFactory es una fábrica de clases que genera objetos COM. El Create crea una nueva fábrica de clases y la añade al ComServer (un objeto global dentro de la unidad ComServ que mantiene una lista de todas las fábricas de clases en este ejecutable). También registra el hecho de que va a instanciar objetos de Delphi TClientes cada vez que Windows necesite una CoClass llamada Class_Clientes (esta CoClass fué generada por la biblioteca de tipos del proyecto automáticamente, y tiene asociado un GUID para ponerlo en el registro de Windows. Vea el capítulo práctico para entender como funciona con un ejemplo).

También notará que el Create le notifica a la fábrica de clases que este objeto es de instancia múltiple y su modelo de hilos de ejecución es "Apartamento".

Por ejemplo, las siguientes gráficas ilustran cómo hace COM para instanciar un objeto a partir de una fábrica de Clases. Cuando un cliente pide la interfase IClientes (1), COM busca en el registro de Windows el GUID que corresponde a IClientes (a menos que usted haya especificado el GUID en vez del nombre), y después busca el ejecutable que corresponde al GUID. Si el archivo no está en memoria, lo ejecuta (2). Una vez hecho esto, COM busca en la lista de la librería de clases (que Delphi guarda en el objeto global ComServer) la fábrica de clases (en rojo) que puede crear IClientes (representado por Class_Clientes en el código fuente arriba) (3).

Después, COM llama al método de la fábrica de clases para crear un objeto, y la fábrica de clases crea un objeto TClientes (4) (usando el método TComObject.CreateFromFactory) y asigna un puntero de interfase, el cual es devuelto a COM (5).

COM a su vez crea un puntero de interfase interno para devolver al cliente (6).

¿Porqué el paso 6? Recuerde que en un ambiente de memoria protegida como es Win32, usted no puede accesar memoria que no le pertenece a su aplicación, así que COM necesita crear un puntero para usted. Esto quiere decir que usted no puede comparar los numeros de puntero en el lado del servidor y del cliente y esperar que sean el mismo. Esto también es util cuando instanciamos un objeto usando DCOM en otra computadora (donde la posición de memoria no tiene sentido en nuestra máquina).

Usted notará que lo complicado en COM ocurre en el servidor, no en el cliente. Lo único que el cliente tiene que hacer es llamar CreateComObject para obtener un puntero de interfase y usarlo. Toda la traducción y lo "Feo" se encuentra en el lado del servidor.

Modelos de Creación de Interfaces COM

El modelo de creación de una interfase se compone de dos secciónes. El modelo de instanciación (instancing model), y el modelo de hilos de ejecución (threading model)

Los modelos de instanciación son como sigue:

Los modelos de hilos de ejecución (threading) son los siguientes:

El mundo de COM es muy grande, y apenas hemos visto suficiente para poder comenzar a hacer un ejemplo y entenderlo. Si este tema le interesa, le recomiendo que compre un buen libro acerca de COM/DCOM y se asome al código fuente de los objetos de Delphi en comobj.pas, ComServ.pas y ActiveX.pas. Espero que esta explicación le haya dado suficientes bases para entender conceptos más avanzados.

Capítulo -->