PROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
Interfaces de Scripting para librerias en C
1. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
Interfaces de scripting para librerías en C
Moisés H. Silva
CIISA 2008
1
2. :: Interfaces de scripting para librerías en C ::
1. Lenguajes de scripting
:: CIISA 2008 ::
Agenda para C en PHP
2. Interfaces
* Funcionamiento.
* ¿Por qué?
* Ventajas y desventajas.
* Extensiones.
* PHP, PERL, Python.
* Zend Engine.
3. Construcción de una Extensión PHP
* Estructuras de registro.
* Variables.
* Funciones.
* Clases.
* Compilación.
2
3. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
Agenda
4. SWIG (Simplified Wrapper and Interface Generator)
* Funcionamiento general
3
4. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Lenguajes de scripting]
Funcionamiento
:: 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.
4
5. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Lenguajes de scripting]
Funcionamiento
5
6. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Lenguajes de scripting]
Ventajas
:: 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.
6
7. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Lenguajes de scripting]
Desventajas
:: 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).
7
8. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Lenguajes de scripting]
PHP, PERL y Python
:: 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.
8
9. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Lenguajes de scripting]
PHP
:: 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.
9
10. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Lenguajes de scripting]
PERL
:: 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.
10
11. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Lenguajes de scripting]
Python
:: 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.
11
12. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Interfaces en C para PHP]
¿Por qué?
:: 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.
12
13. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Interfaces en C para PHP]
Extensiones
:: 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.
13
14. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Interfaces en C para PHP]
Extensiones
14
15. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Interfaces en C para PHP]
Zend Engine
:: 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.
15
16. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Interfaces en C para PHP]
Zend Engine
:: 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.
16
17. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Interfaces en C para PHP]
Zend Engine
:: 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”
17
18. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Interfaces en C para PHP]
Zend Engine
:: 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.
18
19. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Interfaces en C para PHP]
Zend Engine
:: 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.
19
20. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Estructuras de registro
:: 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 ...
20
21. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Estructuras de registro
21
22. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Estructuras de registro
:: 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)
22
23. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Estructuras de registro
:: 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)
23
24. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Variables
:: 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).
24
25. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Variables
25
26. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Variables
:: 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.
26
27. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Funciones
:: 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);
27
28. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Funciones
:: 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()
28
29. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Funciones
:: 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
29
30. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Funciones
:: 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*
30
31. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Funciones
:: 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);
31
32. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Funciones
PHP_FUNCTION(suma)
{
long op1; op2;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"ll", &op1, &op2)) {
return;
}
RETURN_LONG((op1 + op2));
}
32
33. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Funciones
:: 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.
33
34. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Clases
:: 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
34
35. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Clases
:: 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);
};
35
36. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Clases
:: 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);
};
36
37. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[Construcción de una extensión PHP]
Compilación
:: 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
37
38. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[SWIG]
Funcionamiento General
:: 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”
%}
38
39. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
[SWIG]
Funcionamiento General
:: 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
39
40. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
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
41. :: Interfaces de scripting para librerías en C ::
:: CIISA 2008 ::
Gracias.
Moisés Humberto Silva Salmerón
http://www.moythreads.com//
moises.silva@gmail.com
moyhu@mx1.ibm.commoyhu@mx1.ibm.com
41