ARQUITECTURA CORBA ■ CORBA ■ ■ ➨ ■ ■ ■ ■ Angel García Baños ■ Escuela de Ingeniería de Sistemas y Computación ■ Universidad del Valle ■ 27 de Noviembre de 2002 CORBA 3 ■ Mapeo del IDL en lenguajes de programación ■ ➨ C Java C++ Ada-95, SmallTalk, COBOL, Lisp, Phyton, IDLscript » – – – Mapeo del IDL en lenguaje C 4 Mapeo del IDL en lenguaje C Las definiciones habituales de IDL hay que incluirlas tanto en clientes como en implementaciones de objetos, usando: #include<Foo.h> Especificación de la interfase en IDL STUB en C C Java C++ Ada-95, SmallTalk, COBOL, Lisp, Phyton, IDLscript AGB ■ CLIENTE Lenguajes: 3 AGB 2 Mapeo del IDL en lenguajes de programación Lenguajes: – – – – Extensión CORBA del Object Model de OMA. Estructura del ORB. Lenguaje de definición de interfases (IDL). Mapeo del IDL en lenguajes de programación. La interfase de Object. La interfase con el ORB. Los adaptadores de objetos (BOA y POA). Depósito de implementaciones (IMR). El tipo any. Depósito de interfases (IR). Interfase dinámica (DII y DSI). Interoperabilidad (GIOP, IIOP). AGB Este fichero lo genera el compilador IDL a partir del fichero escrito en IDL, digamos Foo.idl Compiladores Object Request Broker (ORB) SKELETO N en C IMPLEMENTACIÓN DEL OBJETO AGB 5 AGB 6 Mapeo del IDL en lenguaje C ■ ■ Mapeo del IDL en lenguaje C Los nombres de tipos, constantes, excepciones y operaciones se derivan de C cambiando "::" por "_". Esto puede traer ambigüedades si el nombre en sí ya lleva "_". Para evitarlas se recomienda no usar indiscriminadamente en C el subrayado "_". Las interfases del IDL deben declararse como globales. Y su mapeo en C se muestra en el siguiente ejemplo: ■ #include<ejemplo1.h> interface ejemplo2 { ejemplo1 op2(); }; interface ejemplo1 { long op1(in long arg1); }; Es equivalente en C a: #include<ejemplo1.h> typedef Object ejemplo2; extern ejemplo1 ejemplo2_op2(ejemplo2 o, Environment *ev); generará en C el siguiente código: typedef Object ejemplo1; extern long ejemplo1_op1(ejemplo1 o, Environment *ev, long arg1); AGB 7 Mapeo del IDL en lenguaje C IDL permite especificar interfases que heredan operaciones de otras interfases: interface ejemplo3 : ejemplo1 { void op3(in long arg3, out long arg4); }; ■ El mapeo de atributos se hace incluyendo en C una función __get y una función __set por cada atributo (ojo, doble “_”). Por ejemplo: interface ej5 { struct coord { float x, y; }; attribute float radio; readonly attribute coord posicion; }; Es equivalente en C a: typedef Object ejemplo3; extern long ejemplo3_op1(ejemplo3 o, Environment *ev, long arg1); extern void ejemplo3_op3(ejemplo3 o ,Environment *ev, long arg3, long *arg4); AGB Los tipos básicos del IDL son los de C, con las siguientes excepciones: – boolean del IDL se mapea como unsigned char en C, pero con typedef struct any {TypeCode _type; void *_value;} any; Los TypeCode son códigos que especifican el tipo de dato. Se enumeran mas adelante, en el capítulo del DII. Las estructuras de IDL se mapean en C como struct. AGB typedef Object ej5; typedef struct ej5_coord { float x, y; } ej5_coord; extern float ej5__get_radio(ej5 o, Environment *ev); extern void ej5__set_radio(ej5 o, Environment *ev, float r); extern ej5_coord ej5__get_posicion(ej5 o, Environment *ev); AGB 10 Mapeo del IDL en lenguaje C sólo dos valores posibles (0=FALSE y 1=TRUE). – octect del IDL se mapea en C como unsigned char. – enum del IDL se mapea en C como un unsigned long para cada elemento de la enumeración. – any del IDL se mapea en C como: ■ Se mapea en C así: 9 Mapeo del IDL en lenguaje C ■ 8 AGB Mapeo del IDL en lenguaje C ■ IDL permite construir interfases con operaciones que hacen referencia (en argumentos, valores de retorno o componentes de tipos construidos) a otras interfases. Por ejemplo: ■ Las uniones discriminadas de IDL se mapean en C como struct conteniendo una unión de nombre obligatorio (_u) y con un campo obligatorio (_d) que sirve para hacer la discriminación. Por ejemplo: typedef struct { long _d; union { long x; float y; char z; } _u; } foo; union foo switch(long) { case 1: long x; case 2: float y; default: char z; }; Se mapea en C así: 11 AGB 12 Mapeo del IDL en lenguaje C ■ Mapeo del IDL en lenguaje C Las secuencias (arrays no dimensionados) se mapean como en el siguiente ejemplo: ■ typedef sequence<long,10> vec10; Pasa a ser en C: typedef struct { unsigned long _maximum; unsigned long _length; long *_buffer; } vec10; Los strings de IDL se mapean en C como arrays de char unidimensionales terminados en 0 (NULL). En C se requiere un byte adicional (para el terminador 0) a la dimensión expresada en IDL. Por ejemplo, en IDL: typedef string <80> nombre; typedef string apellidos; Es equivalente al siguiente código en C: // longitud máxima // longitud en cada instante // puntero a los datos typedef char *nombre; typedef char *apellidos; ■ Y se crea una instancia de este tipo así: En IDL los strings no terminan en 0, pero está prohibido que contengan el 0 en su interior. vec10 x = { 10L, 0L, (long *)NULL }; Las sequence hay que inicializarlas adecuadamente antes de enviarlas a otro objeto AGB 13 Mapeo del IDL en lenguaje C ■ AGB 14 Mapeo del IDL en lenguaje C Los arrays de IDL se mapean como arrays en C. Los índices van desde 0 hasta la dimensión menos 1. Si el resultado de una operación es un array, el stub reserva dinámicamente memoria para él. Cuando el array ya no se necesite mas, es responsabilidad del cliente liberar la memoria llamando a ORBfree() (hay mas información al respecto un poco mas adelante). ■ Cada tipo de excepción se define como un tag y un typedef usando el nombre global de C. También se define (con #define) un string literal identificando la excepción. Por ejemplo, en IDL: exception xx { long param; }; Equivale en C a: typedef struct xx { long param; } xx; #define ex_xx <número identificador biunívoco de la excepción> AGB 15 Mapeo del IDL en lenguaje C ■ 16 Mapeo del IDL en lenguaje C Todas las operaciones tienen 2 o 3 parámetros implícitos adicionales, que preceden a los parámetros reales. El primer parámetro es de entrada, de tipo Object, y sirve para indicar el objeto que debe procesar la petición. El segundo parámetro es de salida, de tipo (Environment *), y sirve para retornar información relativa a excepciones. Puede haber otro parámetro opcional: si se especifica un contexto en IDL, entonces hay un parámetro de entrada, de tipo Context, que va justo después de Environment. AGB AGB 17 ■ El paso de argumentos a una función sigue prácticamente las mismas reglas que en C: cualquier tipo IDL (excepto arrays) que se pase como argumento out o inout debe pasarse su dirección. Si es un array, debe pasarse la dirección del primer elemento. Si se pasa el argumento como in, si es un tipo básico debe pasarse el respectivo valor correspondiente a ese tipo; si es un array debe pasarse la dirección del primer elemento del array; y si es un tipo compuesto debe pasarse la dirección de una variable del tipo en cuestión. Por ejemplo: interface uno { typedef long Vector[25]; void op(out Vector x, out long y); }; AGB 18 Mapeo del IDL en lenguaje C Mapeo del IDL en lenguaje C El código del cliente para invocar la operacion op será: ■ uno object; uno_Vector x; long y; Environment ev; uno_op(object, &ev, x, &y); Cuando hay parámetros out de tipo string, array o sequence no dimensionados, el ORB reserva espacio de memoria dinámicamente para ellos. El cliente puede usar esa memoria todo el tiempo que quiera, pero al final debe liberarla llamando a ORBfree(), cuyo prototipo es: extern void ORBfree(void *storage); El parámetro de esta función es un puntero a la dirección que se quiere liberar. 19 AGB Mapeo del IDL en lenguaje C ■ AGB 20 Mapeo del IDL en lenguaje C Para el manejo de excepciones existe la siguiente declaración en C: typedef struct Environment { exception_type _major; ... } Environment; Después de cualquier llamada, el parámetro _major puede contener uno de estos tres valores: NO_EXCEPTION USER_EXCEPTION SYSTEM_EXCEPTION AGB El mecanismo para retornar resultados es también muy similar al de C. Si el resultado a retornar es de tipo float, double, long, short, unsigned long, unsigned short, char boolean, octect, Object o enum, entonces se retorna el respectivo valor. Si el resultado es de tipo struct, union, sequence o any, entonces se retorna el valor de la estructura de C que representa dicho tipo. Si el resultado es de tipo string o array, se retorna un puntero al primer elemento. Si el resultado es un string, array o sequence no dimensionados, el ORB reservará memoria dinámicamente para ellos, y el cliente la deberá liberar cuando no la vaya a usar mas con ORBfree(). 21 En los dos últimos casos se produjo una excepción, y se puede acceder a los parámetros de ella a través de tres funciones: // Retorna puntero a string identificador de excepción, (ID del IR): extern char *CORBA_exception_id(Environment *ev); // Retorna puntero a la estructura de la excepción: extern void *CORBA_exception_value(Environment *ev); // Libera memoria pedida al crear la excepción: extern void CORBA_exception_free(Environment *ev); // En el sirviente, lanza una excepción: extern void CORBA_exception_set(Environment *ev, exception_type major, char *except_repos_id, void *param); // param debe apuntar a la estructura definida por el usuario AGB 22