Interfaces de Scripting para librerias en C

41
:: CIISA 2008 :: :: Interfaces de scripting para librerías en C :: nterfaces de scripting para librerías en CIISA 2008 Moisés H. Silva 1

description

Entendiendo como extender lenguajes de scripting como PHP con extensiones en C

Transcript of Interfaces de Scripting para librerias en C

Page 1: 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

Page 2: Interfaces de Scripting para librerias en C

:: 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

Page 3: Interfaces de Scripting para librerias en C

:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::

Agenda

4. SWIG (Simplified Wrapper and Interface Generator)

* Funcionamiento general

3

Page 4: Interfaces de Scripting para librerias en C

:: 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.

Page 5: Interfaces de Scripting para librerias en C

:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::

[Lenguajes de scripting]

Funcionamiento

5

Page 6: Interfaces de Scripting para librerias en C

:: 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.

Page 7: Interfaces de Scripting para librerias en C

:: 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).

Page 8: Interfaces de Scripting para librerias en C

:: 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.

Page 9: Interfaces de Scripting para librerias en C

:: 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.

Page 10: Interfaces de Scripting para librerias en C

:: 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.

Page 11: Interfaces de Scripting para librerias en C

:: 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.

Page 12: Interfaces de Scripting para librerias en C

:: 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.

Page 13: Interfaces de Scripting para librerias en C

:: 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.

Page 14: Interfaces de Scripting para librerias en C

:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::

[Interfaces en C para PHP]

Extensiones

14

Page 15: Interfaces de Scripting para librerias en C

:: 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.

Page 16: Interfaces de Scripting para librerias en C

:: 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.

Page 17: Interfaces de Scripting para librerias en C

:: 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”

Page 18: Interfaces de Scripting para librerias en C

:: 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.

Page 19: Interfaces de Scripting para librerias en C

:: 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.

Page 20: Interfaces de Scripting para librerias en C

:: 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 ...

Page 21: Interfaces de Scripting para librerias en C

:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::

[Construcción de una extensión PHP]

Estructuras de registro

21

Page 22: Interfaces de Scripting para librerias en C

:: 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)

Page 23: Interfaces de Scripting para librerias en C

:: 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)

Page 24: Interfaces de Scripting para librerias en C

:: 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).

Page 25: Interfaces de Scripting para librerias en C

:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::

[Construcción de una extensión PHP]

Variables

25

Page 26: Interfaces de Scripting para librerias en C

:: 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.

Page 27: Interfaces de Scripting para librerias en C

:: 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);

Page 28: Interfaces de Scripting para librerias en C

:: 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()

Page 29: Interfaces de Scripting para librerias en C

:: 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

Page 30: Interfaces de Scripting para librerias en C

:: 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*

Page 31: Interfaces de Scripting para librerias en C

:: 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);

Page 32: Interfaces de Scripting para librerias en C

:: 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));}

Page 33: Interfaces de Scripting para librerias en C

:: 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.

Page 34: Interfaces de Scripting para librerias en C

:: 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

Page 35: Interfaces de Scripting para librerias en C

:: 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); };

Page 36: Interfaces de Scripting para librerias en C

:: 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); };

Page 37: Interfaces de Scripting para librerias en C

:: 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

Page 38: Interfaces de Scripting para librerias en C

:: 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”%}

Page 39: Interfaces de Scripting para librerias en C

:: 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

Page 40: Interfaces de Scripting para librerias en C

:: 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

Page 41: Interfaces de Scripting para librerias en C

:: CIISA 2008 :::: Interfaces de scripting para librerías en C ::

Moisés Humberto Silva Salmerón

http://www.moythreads.com//

[email protected]

[email protected]@mx1.ibm.com

Gracias.

41