Title: Interfaces de scripting para librer
1Interfaces de scripting para librerÃas en C
CIISA 2008
Moisés H. Silva
1
2Agenda
1. Lenguajes de scripting Funcionamiento.
Ventajas y desventajas. PHP, PERL, Python.
2. 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.
2
3Agenda
4. SWIG (Simplified Wrapper and Interface
Generator) Funcionamiento general
3
4Lenguajes 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
5Lenguajes de scripting
Funcionamiento
5
6Lenguajes 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
7Lenguajes 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
8Lenguajes 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
9Lenguajes 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
10Lenguajes 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
11Lenguajes 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
12Interfaces 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
13Interfaces 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
14Interfaces en C para PHP
Extensiones
14
15Interfaces 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
16Interfaces en C para PHP
Zend Engine
El ciclo de vida de una extensión de PHP se
compone de 5 etapas -gt Inicialización El
proceso donde habita el core es iniciado. -gt
Activación Cada vez que la extensión es usada
por un nuevo script. -gt Ejecución El script
hace uso de la funcionalidad de la
extensión. -gt Desactivación El script
finalizó. -gt Finalización El proceso donde
habita el core está siendo terminado.
16
17Interfaces en C para PHP
Zend Engine
El ZE expone APIs a sus extensiones para -gt
Manejo de memoria. -gt Creación y manipulación
de variables. -gt Reference counting. -gt
Consulta de las configuraciones del INI. -gt
Registro de clases y funciones. -gt Obtención y
retorno de variables de user space
17
18Interfaces en C para PHP
Zend Engine
Dentro de ambiente del ZE, existen 2 tipos de
memoria -gt Memoria persistente o no
manejada. -gt 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
19Interfaces 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 -gt PHP_API int printf(const char
format, ...) -gt PHP_API int php_body_write(const
char str, uint str_length TSRMLS_DC) -gt
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
20Construcció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 -gt Nombre de
la extensión. -gt Lista de funciones y sus
manejadores. -gt Apuntadores a funciones de
inicialización y destrucción. -gt Versión del
módulo. -gt Otras propiedades generales ...
20
21Construcción de una extensión PHP
Estructuras de registro
21
22Construcció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
23Construcció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(hello
ext) Los macros generan el prototipo
apropiado, como int zm_activate_helloext(int
type, int module_number TSRMLS_DC)
23
24Construcció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
variable0 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
25Construcción de una extensión PHP
Variables
25
26Construcció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 ltdireccion
de memoria de un hash tablegt Las propiedades
del zval cambian conforme al flujo del
script. Todas las extensiones recibirán zvals
representando variables del usuario.
26
27Construcció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
28Construcció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 -gt Recepción y
parseo de argumentos con zend_parse_parameters()
-gt Proceso especÃfico de la función. -gt
Retorno de un valor mediante los macros
RETURN_XXX()
28
29Construcció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
30Construcción de una extensión PHP
Funciones
La cadena de formato puede contener los
valores s -gt el valor esperado es un string.
Debemos proveer char e int b -gt booleano.
Proveer zend_bool l -gt long. Proveer long r,
a, o, z -gt resource, array, object, opaco.
Proveer zval
30
31Construcció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_l
ocal, 0)
31
32Construcció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
33Construcció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
34Construcció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_intern
al_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
35Construcció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
36Construcció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
37Construcció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 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 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 -MextUtilsEmbed -e
ccopts Se enlaza la libreria con el wrapper
de perl. ld -G milibreria.o milibreria_wrap.o
-o milibreriaperl.so
39
40Referencias.
http//www.hardened-php.net/ http//devzone.zend.
com/ http//www.php.net/ http//www.swig.org/ h
ttp//www.php.net/internals2.ze1.zendapi
40
41Gracias.
Moisés Humberto Silva Salmerón http//www.moythre
ads.com// moises.silva_at_gmail.com moyhu_at_mx1.ibm.c
ommoyhu_at_mx1.ibm.com
41