Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Interfaces de Scripting para librerias en C

1,080 views

Published on

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

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Interfaces de Scripting para librerias en C

  1. 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. 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. 3. :: Interfaces de scripting para librerías en C :: :: CIISA 2008 :: Agenda 4. SWIG (Simplified Wrapper and Interface Generator) * Funcionamiento general 3
  4. 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. 5. :: Interfaces de scripting para librerías en C :: :: CIISA 2008 :: [Lenguajes de scripting] Funcionamiento 5
  6. 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. 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. 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. 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. 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. 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. 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. 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. 14. :: Interfaces de scripting para librerías en C :: :: CIISA 2008 :: [Interfaces en C para PHP] Extensiones 14
  15. 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. 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. 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. 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. 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. 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. 21. :: Interfaces de scripting para librerías en C :: :: CIISA 2008 :: [Construcción de una extensión PHP] Estructuras de registro 21
  22. 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. 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. 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. 25. :: Interfaces de scripting para librerías en C :: :: CIISA 2008 :: [Construcción de una extensión PHP] Variables 25
  26. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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

×