Interfaces de Scripting para librerias en C
-
Upload
moises-silva -
Category
Technology
-
view
615 -
download
0
description
Transcript of Interfaces de Scripting para librerias en C
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
Interfaces de scripting para librerías en CCIISA 2008Moisés H. Silva
1
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
Agenda2. Interfaces para C en PHP
* ¿Por qué?
* Extensiones.
* Zend Engine.
3. Construcción de una Extensión PHP
* Estructuras de registro.
* Variables.
* Funciones.
* Clases.
* Compilación.
1. Lenguajes de scripting
* Funcionamiento.
* Ventajas y desventajas.
* PHP, PERL, Python.
2
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
Agenda
4. SWIG (Simplified Wrapper and Interface Generator)
* Funcionamiento general
3
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Lenguajes de scripting]
Funcionamiento
4
:: Los lenguajes de scripting son comunmente conocidos como interpretados.
:: El intérprete es un programa que se encarga de parsear y ejecutar las instrucciones indicadas en el script (código del programa).
:: A diferencia de los lenguajes compilados, el lenguaje de scripting siempre depende de su interprete para poder ser ejecutado.
:: Comunmente son menos estrictos con los tipos de datos y las operaciones que se pueden realizar entre los distintos tipos de variables. Son dinámicos.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Lenguajes de scripting]
Funcionamiento
5
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Lenguajes de scripting]
Ventajas
6
:: Manejo de memoria automático.
:: Tiempo de desarrollo mucho menor comparado con lenguajes compilados.
:: La curva de aprendizaje es menos pronunciada.
:: Amplio espectro de bibliotecas/librerías usualmente disponibles con el interprete.
:: Alto nivel de portabilidad.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Lenguajes de scripting]
Desventajas
7
:: Baja eficiencia. (Tiempo de ejecución prolongado)
:: Usualmente limitados al universo de funcionalidad proveido por el intérprete y sus extensiones.
:: Bugs que usualmente pueden ser encontrados en tiempo de compilación ahora pueden esconderse hasta su ejecución.
:: Código fuente usualmente expuesto (no necesariamente una desventaja).
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Lenguajes de scripting]
PHP, PERL y Python
8
:: Son 3 de los lenguajes de scripting más usados, particularmente en Linux.
:: Sus intérpretes son de fuente abierta (open source).
:: Todos han sido usados para aplicaciones web con éxito.
:: Soportan orientación a objetos.
:: Se encuentran soportados por el generador de interfaces SWIG.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Lenguajes de scripting]
PHP
9
:: Creado por Rasmus Lerdof a mediados de los 90.
:: Inicio como una serie de CGIs en C para generar páginas web de forma dinámica.
:: PHP evolucionó de forma desorganizada por mucho tiempo.
:: La compañia Zend le ha dado forma al lenguaje para ser más robusto.
:: Soporta código estructurado y orientado a objetos.
:: Su sintaxis es muy similar a C++ con algunas ideas tomadas de Java.
:: Aunque su fuerte es la creación de sitios web, puede ser usado como de propósito general.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Lenguajes de scripting]
PERL
10
:: Creado por Larry Wall a finales de los 80.
:: Lenguaje de scripting de propósito general.
:: Muy popular sobre todo en Linux para la automatización de tareas en servidores.
:: Al igual que PHP ha ido evolucionando y agregando nuevas características como la orientación a objetos.
:: Siempre expone muchas formas de hacer la misma tarea.
:: La sintaxis puede llegar a ser muy extraña.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Lenguajes de scripting]
Python
11
:: Escrito por Guido van Rossum a principios de los 90.
:: Su modelo de programación es principalmente orientado a objetos.
:: Programación estructurada y funcional también soportadas en menor medida.
:: Curiosamente usa los “tabs” para definir bloques de código.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Interfaces en C para PHP]
¿Por qué?
12
:: Soportar funcionalidad solo disponible en librerías en C/C++
:: Exponer interfaces mas simples y/u orientadas a objetos a los usuarios.
:: Mejorar el performance de tus scripts.
:: Distribuir módulos de funcionalidad sin código fuente.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Interfaces en C para PHP]
Extensiones
13
:: Las extensiones de PHP son shared object's o DLL's que exponen funcionalidad no disponible en el core de PHP.
:: Al iniciar, el core de PHP carga las extensiones requeridas por el script de entrada.
:: Las extensiones proveen de su funcionalidad a través de funciones, clases, constantes etc.
:: Cada extensión es responsable de sus recursos. El usuario de la extensión no tiene porque preocuparse de la liberación de recursos.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Interfaces en C para PHP]
Extensiones
14
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Interfaces en C para PHP]
Zend Engine
15
:: El Zend Engine es lo que se conoce como el core de PHP.
:: Se encarga del manejo de memoria y toda la funcionalidad básica de un intérprete.
:: Las extensiones pueden ser cargadas por el ZE ó compiladas de forma interna.
:: El ZE lleva a cabo el manejo de los ciclos de vida de las extensiones y los scripts.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Interfaces en C para PHP]
Zend Engine
16
:: El ciclo de vida de una extensión de PHP se compone de 5 etapas:
-> Inicialización: El proceso donde habita el core es iniciado.
-> Activación: Cada vez que la extensión es usada por un nuevo script.
-> Ejecución: El script hace uso de la funcionalidad de la extensión.
-> Desactivación: El script finalizó.
-> Finalización: El proceso donde habita el core está siendo terminado.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Interfaces en C para PHP]
Zend Engine
17
:: El ZE expone APIs a sus extensiones para:
-> Manejo de memoria.
-> Creación y manipulación de variables.
-> Reference counting.
-> Consulta de las configuraciones del INI.
-> Registro de clases y funciones.
-> Obtención y retorno de variables de “user space”
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Interfaces en C para PHP]
Zend Engine
18
:: Dentro de ambiente del ZE, existen 2 tipos de memoria:
-> Memoria persistente o no manejada.
-> Memoria de request o manejada.
:: La memoria persistente es aquella no manejada por el ZE, como aquella memoria solicitada via malloc y por funciones ajenas al ZE.
:: La memoria de request o manejada es aquella solicitada por APIs del ZE como emalloc(), ecalloc(), erealloc(), estrdup() etc.
:: La memoria de request o manejada solo persiste durante un hit de una página web.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Interfaces en C para PHP]
Zend Engine
19
:: El I/O de datos también es controlado por el ZE.
:: El ZE expone algunas API para la salida de datos:
-> PHP_API int printf(const char *format, ...)-> PHP_API int php_body_write(const char *str, uint str_length TSRMLS_DC)-> ZEND_API int zend_print_variable(zval *var)
:: El uso directo de stdout debe ser evitado, sobretodo cuando php está corriendo en un ambiente web debido a que la salida en realidad la salida usualmente es dirigida por el ZE a la interfaz del servidor web.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Estructuras de registro
20
:: El ZE carga las extensiones usando información obtenida de una estructura llamada zend_module_entry.
:: zend_module_entry define datos generales de la extensión:
-> Nombre de la extensión.
-> Lista de funciones y sus manejadores.
-> Apuntadores a funciones de inicialización y destrucción.
-> Versión del módulo.
-> Otras propiedades generales ...
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Estructuras de registro
21
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Estructuras de registro
22
:: Las funciones de inicialización (MINIT) y destrucción (MSHUTDOWN) de módulo son llamadas una sola vez en la vida de la extensión.
:: Durante MINIT se deben registrar las clases, constantes y demás funcionalidad que será expuesta al usuario.
:: Durante MSHUTDOWN deben liberarse los recursos que pudieran haber sido solicitados en MINIT.
:: La declaración de MINIT y MSHUTDOWN se hace a través de macros:
PHP_MINIT_FUNCTION(helloext){}PHP_MSHUTDOWN_FUNCTION(helloext){}
:: Los macros generan el prototipo apropiado, como:
int zm_startup_helloext(int type, int module_number TSRMLS_DC)
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Estructuras de registro
23
:: Las funciones de inicialización (RINIT) y destrucción (RSHUTDOWN) de request son llamadas una vez por request.
:: Durante RINIT se deben solicitar los recursos que no permanecen durante requests.
:: Durante RSHUTDOWN deben liberarse los recursos que fueron solicitados durante la ejecución del script, como conexiones a BD no persistentes.
:: La declaración de RINIT y RSHUTDOWN se hace a través de macros:
PHP_RINIT_FUNCTION(helloext){}PHP_RSHUTDOWN_FUNCTION(helloext){}
:: Los macros generan el prototipo apropiado, como:
int zm_activate_helloext(int type, int module_number TSRMLS_DC)
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Variables
24
:: Para los usuarios de PHP una variable puede cambiar de tipo de forma dinámica sin problema alguno.
$variable = array('uno', 'dos');print $variable[0];$variable = 10;print $variable;
:: PHP soporta los tipos Integer, Float, String, Boolean, Array, Object, Resource y NULL
:: Internamente una variable es representada por la estructura zval.
:: zval contiene la información necesaria para determinar el tipo de la variable, su valor, si es una referencia y cuantas referencias hay hacia la variable (reference counting).
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Variables
25
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Variables
26
:: Internamente, un statement como $var = “valor”; resulta en un zval con:
.type = 6; /* macro IS_STRING */
.value.str = { val = “valor”; len = 5; }
.is_ref = 0;
.refcount = 1;
:: Al reasignar $var = array(“valor”);, el mismo zval se usa y se modifica su tipo:
.type = 4; /* macro IS_ARRAY */ .value.ht = <direccion de memoria de un hash table>
:: Las propiedades del zval cambian conforme al flujo del script.
:: Todas las extensiones recibirán zvals representando variables del usuario.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Funciones
27
:: Las funciones de PHP internamente son prefijadas con zif_ y reciben parámetros estandar.
:: El macro PHP_FUNCTION ayuda en la definición del prototipo.
:: La definición resultante es:
void zif_nombrefuncion(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC, void ***tsrm_ls);
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Funciones
28
:: El macro PHP_FUNCTION recibe como argumento el nombre de la función que deseamos exportar.
PHP_FUNCTION(suma)
:: El cuerpo de la función usualmente consta de:
-> Recepción y parseo de argumentos con zend_parse_parameters()
-> Proceso específico de la función.
-> Retorno de un valor mediante los macros RETURN_XXX()
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Funciones
29
:: zend_parse_parameters es necesario para tomar los argumentos del stack del ZE.
:: zend_parse_parameters recibe el número de argumentos a parsear, sus tipos (mediante una cadena de formato) y los apuntadores a la memoria a utilizar para guardarlos.
int op1, op2; zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
“ll”, &op1, &op2);
:: El valor de retorno FAILURE significa que el parseo falló y usualmente debe ser causal para mandar un error con zend_throw_exception o WRONG_PARAM_COUNT
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Funciones
30
:: La cadena de formato puede contener los valores:
s -> el valor esperado es un string. Debemos proveer char ** e int*
b -> booleano. Proveer zend_bool*
l -> long. Proveer long*
r, a, o, z -> resource, array, object, opaco. Proveer zval*
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Funciones
31
:: Para regresar un valor de la función debe usarse:
RETURN_RESOURCE, RETURN_LONG, RETURN_BOOL etc.
:: RETURN_STRING es especial, debe indicarse si el buffer del string debe ser duplicado o no por el ZE. El segundo parámetro del macro lo indica.
RETURN_STRING(“Buffer Permanente”, 1);RETURN_STRING(variable_local, 0);
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Funciones
32
PHP_FUNCTION(suma){ long op1; op2; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &op1, &op2)) { return; } RETURN_LONG((op1 + op2));}
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Funciones
33
:: TSRMLS == Thread Safe Resource Manager Local Storage
:: Necesario para crear scope “global” por thread.
:: Existen muchos macros variantes para facilitar pasar este storage de un lado a otro.
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Clases
34
:: El ZE está escrito en C por lo que internamente las clases de PHP están definidas como estructuras y apuntadores a funciones.
:: Una declaración en user space de una clase tiene la forma:
class ClaseEnPhp {}
:: Internamente tal clase tendría que registrarse usando una estructura zend_class_entry y la función zend_register_internal_class.
:: El equivalente a una declaración de clase en user space es:
zend_class_entry ce;INIT_CLASS_ENTRY(ce, “ClaseEnPhp”, NULL);zend_register_internal_class(&ce TSRML_CC);
:: El registro de clases desde una extensión debe ser hecho en MINIT
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Clases
35
:: La implementación de un método de una varía poco de la de una función común.
:: El macro PHP_METHOD es usado en lugar de PHP_FUNCTION.
PHP_METHOD(PrimerMetodo){
// cuerpo del método}
:: Características adicionales para el método como visibilidad y definición de argumentos son especificadas a través de la estructura zend_function_entry y el macro PHP_ME
zend_function_entry ClaseEnPhp_methods[] = { PHP_ME(ClaseEnPhp, PrimerMetodo, NULL, ZEND_ACC_PUBLIC); };
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Clases
36
:: La implementación de un método de una varía poco de la de una función común.
:: El macro PHP_METHOD es usado en lugar de PHP_FUNCTION.
PHP_METHOD(PrimerMetodo){
// cuerpo del método}
:: Características adicionales para el método como visibilidad y definición de argumentos son especificadas a través de la estructura zend_function_entry y el macro PHP_ME
zend_function_entry ClaseEnPhp_methods[] = { PHP_ME(ClaseEnPhp, PrimerMetodo, NULL, ZEND_ACC_PUBLIC); };
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[Construcción de una extensión PHP]
Compilación
37
:: La compilación en Linux se lleva a cabo mediante un comando incluido con la distribución de PHP: “phpize”
:: Antes de correr phpize se necesita crear config.m4, un script que determinará opciones de tiempo de compilación como la ubicación de librerías externas.
:: Una vez creado config.m4 se procede a ejecutar phpize
# phpize
:: Finalmente igual que cualquier otro paquete basado en GNU autotools se instala mediante:
# ./configure# make && make install
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[SWIG]
Funcionamiento General
38
:: SWIG es un generador del pegamento necesario para juntar código en C/C++ con lenguajes de más alto nivel como PHP, PERL, Python, Java etc.
:: SWIG recibe como entrada un archivo especial que define las interfaces en C/C++ para generar código fuente que puede ser compilado para crear módulos del lenguaje deseado.
:: Una archivo de interfaz puede ser facilmente escrito incluyendo el header donde declaras tus funciones C/C++:
%module milibreria%{#include “milibreria.h”%}
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
[SWIG]
Funcionamiento General
39
:: El archivo de interfaz se usa como entrada para SWIG.
# swig -perl milibreria.i
:: SWIG genera un archivo milibreria_wrap.c que funcionará como interfaz hacia PERL.
:: Se compila la interfaz.
# gcc -c milibreria.c milibreria_wrap.c `perl -MextUtils::Embed -e ccopts`
:: Se enlaza la libreria con el wrapper de perl.
# ld -G milibreria.o milibreria_wrap.o -o milibreriaperl.so
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
Referencias.
http://www.hardened-php.net/
http://devzone.zend.com/
http://www.php.net/
http://www.swig.org/
http://www.php.net/internals2.ze1.zendapi
40
:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::
Moisés Humberto Silva Salmerón
http://www.moythreads.com//
[email protected]@mx1.ibm.com
Gracias.
41