Your SlideShare is downloading. ×
PHPSC Conference 2010 - Desenvolvimento de Extensões PECL
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

931
views

Published on

Published in: Technology

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
931
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
9
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. PHPSC Conference 2010 Desenvolvimento de extensões PECL Erick Belluci Tedeschi - @ericktedeschi    
  • 2. Agenda ­ O que é PECL? ­ Motivação ­ PHP LifeCycle ­ Estrutura ZVAL ­ Ambiente de Desenvolvimento (*nix) ­ ext_skel (Esqueleto de uma extensão) ­ API Zend ­ Aceitando parâmetros ­ Exemplo: Função recebendo parâmetro e retornando  valor ­ C com OOP? * Live DEMO :­D    
  • 3. Quem é Erick Tedeschi? Conheceu PHP em 2003 Analista de Segurança da Informação  Doctrine (extensão PECL classe Lexer) Motociclista Obs.: ..ñ é Takashi, Takeshi, Takeushi..É TEDESCHI    
  • 4. O que é PECL? PHP Extension and Application Repository    
  • 5. O que é PECL? PHP Extension and Application Repository PHP Extension Community Library    
  • 6. O que é PECL? ← Escrito em PHP PHP Extension and Application Repository ← Escrito em “C” PHP Extension Community Library    
  • 7. Motivação!!! heee Aumento de performance Adicionar novas funcionalidades Embarcar PHP    
  • 8. PHP Page Life Cycle Ciclo de vida de uma requisição de página (script) PHP originada de um WebServer: Processo do Apache Inicia WebServer LoadModule php5_module Carrega módulo do PHP mysql,sockets,curl,curses,etc... PHP Carrega suas extensões (built­in e php.ini) MINIT Carrega constantes, ini entries, resources, etc... RINIT Inicializa autoglobals, symbol table, log, etc... Script Execution RSHUTDOWN Libera memória... MSHUTDOWN Libera memória... (ini entries, resources, etc...)    
  • 9. Estrutura ZVAL typedef struct _zval_struct { typedef union _zvalue_value { zvalue_value value; long lval; // Long,Bool,Resource zend_uint refcont; double dval; // Double zend_uchar type; struct { zend_uchar is_ref; char *val; } zval; long length; } str; // String HashTable *ht; // Array zend_object_value obj; // Object } zvalue_value; IS_NULL IS_BOOL IS_LONG IS_DOUBLE IS_STRING IS_ARRAY IS_OBJECT IS_RESOURCE    
  • 10. Ambiente de Desenvolvimento (*nix) Requisitos necessários para compilar extensões: Ubuntu: m4 e build­essential ­ autoconf 2.13   (http://ftp.gnu.org/gnu/autoconf) ­ automake 1.4   (http://ftp.gnu.org/gnu/automake) ­ libtool 1.4.x+ (except 1.4.2)   (http://ftp.gnu.org/gnu/libtool) ­ bison 1.28   (http://ftp.gnu.org/gnu/bison) ­ flex 2.5.4   (http://prdownloads.sourceforge.net/flex/flex­2.5.4a.tar.gz?download) ­ re2c 0.13.4+   (http://re2c.org)     * Caso a extensão faça uso de alguma bilioteca externa, a mesma deve ser Instalada: Libcurses­dev, libxml­dev, etc...
  • 11. Esqueleto da Extensão – Arquivos Arquivos básicos que compõe a extensão: Obrigatórios: ­ config.m4   Arquivo de configuração *unix ­ config.w32   Arquivo de configuração Windows ­ php_EXTNAME.h   Cabeçalho (includes, structs, protótipo de funções, macros, etc...) ­ EXTNAME.c   Esqueleto da extensão e implementação das funções/classes     Obs.: EXTNAME é o nome da extensão criada
  • 12. Esqueleto da Extensão – Arquivos Arquivos básicos que compõe a extensão: Opcionais: ­ CREDITS   1ª linha Nome da Extensão, 2ª linha em diante nome dos colaboradores ­ EXPERIMENTAL   Não estável. Conteúdo: observação sobre o que está instável ou o que      pode ser alterado. ­ EXTNAME.php   Teste básico da extensão ­ tests   Diretório onde ficam os casos de teste escritos para a extensão     Obs.: EXTNAME é o nome da extensão criada
  • 13. Script: ext_skel O script ext_skel fica localizado dentro do diretório “ext” na raiz do source do PHP. A  extensão  gerada  é  uma  cópia  dos  arquivos  do  diretório  “ext/skeleton”,  substituindo  apenas  o  nome  da  extensão  definida  no  parâmetro  “­­extname”  do  script ext_skel. fulano@machine:/home/dev/php-5.3/ext$ ./ext_skel –extname=phpsc fulano@machine:/home/dev/php-5.3/ext$ cd phpsc fulano@machine:/home/dev/php-5.3/ext/phpsc$ ls -lh -rw-r--r-- 1 kirex kirex 2,0K 2010-08-28 10:25 config.m4 -rw-r--r-- 1 kirex kirex 289 2010-08-28 10:25 config.w32 -rw-r--r-- 1 kirex kirex 5 2010-08-28 10:25 CREDITS -rw-r--r-- 1 kirex kirex 0 2010-08-28 10:25 EXPERIMENTAL -rw-r--r-- 1 kirex kirex 2,8K 2010-08-28 10:25 php_phpsc.h -rw-r--r-- 1 kirex kirex 5,1K 2010-08-28 10:25 phpsc.c -rw-r--r-- 1 kirex kirex 499 2010-08-28 10:25 phpsc.php drwxr-xr-x 2 kirex kirex 4,0K 2010-08-28 10:25 tests    
  • 14. API – Macros e mais macros de macros! Com macros (menor margem para erros): zval *nome = NULL; ALLOC_ZVAL(nome); ZVAL_STRING(nome, “Cássia”, 0); Sem macros (maior margem para erros): zval *nome = NULL; nome = (zval *)emalloc(sizeof(zval)); (*nome).value.str.len = strlen(“Cássia”); (*nome).value.str.value = estrndup(“Cássia”, strlen(“Cássia”);   (*nome).type = 6; /* IS_STRING */  
  • 15. Esqueleto da Extensão – config.m4 PHP_ARG_ENABLE(EXTNAME, Whether to enable the EXTNAME extension, [ --enable-EXTNAME Enable extension description ]) If test $PHP_EXTNAME != “no”; then PHP_NEW_EXTENSION(EXTNAME, EXTNAME.c, $ext_shared) fi Obs.:  Sempre  que  alterar  o  config.m4,  executar  o  phpize  para  gerar  novamente o script “configure” e outros arquivos que são utilizados para  compilar a extensão.    
  • 16. Esqueleto da Extensão – php_EXTNAME.h #ifndef PHP_EXTNAME_H /* Prevent double inclusion */ #define PHP_EXTNAME_H /* Define extension properties */ #define PHP_EXTNAME_NAME “Extension Name for Minfo” #define PHP_EXTNAME_VER “1.0” /* Import configure options when building outside Of the PHP source tree */ #ifdef HAVE_CONFIG_H #include “config.h” #endif /* Include PHP standard header */ #include “php.h” /* Define the entry point symbol. Zend will use when loading this module */ extern zend_module_entry extname_module_entry; #define phpext_EXTNAME_ptr &extname_module_entry   #endif /* PHP_EXTNAME_H */  
  • 17. Esqueleto da Extensão - EXTNAME.c Estrutura do arquivo “.c”: cabeçalho Licença, Créditos, Descrição, etc... includes API e bibliotecas externas funções Funções existentes na extensão MINFO Informações do módulo (phpinfo()) MINIT Tarefas a serem executadas ao carregar a extensão MSHUTDOWN Libera memórias das tarefas executadas no MINIT RINIT Tarefas a serem executadas na requisição do script PHP RSUTDOWN Libera memória das tarefas executadas no RINIT function_entry Registra as funções para a extensão module_entry Entrada do módulo no PHP    
  • 18. Esqueleto da Extensão - Cabeçalho /* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Fulano de Tal < fulano at tal dot com > | +----------------------------------------------------------------------+ */ /* $Id: header 252479 2008-02-07 19:39:50Z iliaa $ */    
  • 19. Esqueleto da Extensão - Includes /* Créditos … */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_EXTNAME.h"    
  • 20. Esqueleto da Extensão - Funções // Exemplo de funções definidas para o “user space”. PHP_FUNCTION(mysql_connect) { /* código da função */ } PHP_FUNCTION(mysql_close) { /* código da função */ } // Exemplo da implementação de classes para o “user space”. PHP_METHOD(Cachorro, __construct) { /* código do construtor */ } PHP_METHOD(Cachorro, latir) { /* código do método */ }   
  • 21. Esqueleto da Extensão - MINFO static PHP_MINFO_FUNCTION(libxml) { php_info_print_table_start(); php_info_print_table_row(2, "libXML support", "active"); php_info_print_table_row(2, "libXML Compiled Version", LIBXML_DOTTED_VERSION); php_info_print_table_row(2, "libXML Loaded Version", (char *)xmlParserVersion); php_info_print_table_row(2, "libXML streams", "enabled"); php_info_print_table_end(); }    
  • 22. Esqueleto da Extensão - MINIT/MSHUTDOWN PHP_MINIT_FUNCTION(extname) { REGISTER_INI_ENTRIES(); return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(extname) { UNREGISTER_INI_ENTRIES(); return SUCCESS; }    
  • 23. Esqueleto da Extensão - RINIT/RSHUTDOWN PHP_RINIT_FUNCTION(extname) { return SUCCESS; } PHP_RSHUTDOWN_FUNCTION(extname) { return SUCCESS; }    
  • 24. Esqueleto da Extensão – Function Entry const zend_function_entry extname_functions[] = { PHP_FE(extname_abrir, NULL) PHP_FE(extname_colar, NULL) PHP_FE(extname_recortar, NULL) {NULL, NULL, NULL} /* Must be the last line in extname_functions[] */ };    
  • 25. Esqueleto da Extensão – Module Entry zend_module_entry extname_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "extname", extname_functions, PHP_MINIT(extname), PHP_MSHUTDOWN(extname), PHP_RINIT(extname), PHP_RSHUTDOWN(extname), PHP_MINFO(extname), #if ZEND_MODULE_API_NO >= 20010901 "0.1", /* Version number for your extension */ #endif STANDARD_MODULE_PROPERTIES };    
  • 26. API ZEND – Manipulação ZVAL Macros para manipulação de ZVAL ZVAL_RESOURCE(zval, 234) ZVAL_NULL(zval) ZVAL_BOOL(zval, 1) ZVAL_LONG(zval, 1234) ZVAL_DOUBLE(zval, 34.5); ZVAL_STRING(zval, “Fulano”, 0) ZVAL_EMPTY_STRING(zval) ZVAL_FALSE(zval) // ZVAL_BOOL(zval, 0) ZVAL_TRUE(zval) // ZVAL_BOOL(zval, 1) Macros para manipulação do valor de retorno da função RETVAL_RESOURCE(234) // ZVAL_RESOURCE(return_value, 234) RETVAL_BOOL(1) // ZVAL_BOOL(return_value, 1) RETVAL_NULL() // ZVAL_NULL(return_value) RETVAL_LONG(1234) // ZVAL_LONG(return_value, 1234) RETVAL_DOUBLE(34.5) // ZVAL_DOUBLE(return_value, 34.5) RETVAL_STRING(“Fulano”, 0) // ZVAL_STRING(return_value, “Fulano”, 0) RETVAL_FALSE RETVAL_TRUE     etc...
  • 27. API ZEND – Manipulação Arrays PHP_FUNCTION(retorna_array) { array_init(return_value); add_assoc_long(return_value, “Numero”, 1234); add_assoc_bool(return_value, “Verdade”, 1); add_assoc_double(return_value, “Peso”, 27.4); } <?php print_r(retorna_array()); ?> Resultado { [Numero] => 1234 [Verdade] => 1 [Peso] => 27.4 } int add_assoc_long(zval *arg, char *key, long n); int add_assoc_null(zval *arg, char *key); int add_assoc_bool(zval *arg, char *key, int b); int add_assoc_resource(zval *arg, char *key, int r); int add_assoc_double(zval *arg, char *key, double d); int add_assoc_string(zval *arg, char *key, char *str, int dup); int add_assoc_stringl(zval *arg, char *key, char *str, uint len, int dup);     int add_assoc_zval(zval *arg, char *key, zval *value);
  • 28. API ZEND – Manipulação Arrays Adiciona com um número de índice específico int add_index_long(zval *arg, uint idx, long n); int add_index_null(zval *arg, uint idx); int add_index_bool(zval *arg, uint idx, int b); int add_index_resource(zval *arg, uint idx, int r); int add_index_double(zval *arg, uint idx, double d); int add_index_string(zval *arg, uint idx, char *str, int duplicate); int add_index_stringl(zval *arg, uint idx, char *str, uint length, int duplicate); int add_index_zval(zval *arg, uint idx, zval *value); Adiciona no próximo índice int add_next_index_long(zval *arg, long n); int add_next_index_null(zval *arg); int add_next_index_bool(zval *arg, int b); int add_next_index_resource(zval *arg, int r); int add_next_index_double(zval *arg, double d); int add_next_index_string(zval *arg, char *str, int duplicate); int add_next_index_stringl(zval *arg, char *str, uint length, int duplicate); int add_next_index_zval(zval *arg, zval *value);    
  • 29. Aceitando Parâmetros Syntax: zend_parse_parameters(num_args, “format args”, &arg1, &arg2, ...) l Long long * d double double * b Boolean zend_bool * a array zval ** o Object zval ** O Object zval **, zend_class_Entry * Força ser da classe/tipo determinada s String char **, int * Sempre recebe string e tamanho r resource zval ** z zval zval ** Z zval-ref zval *** | Restante (parte direita) são opcionais !   Proximo parametro retorna NULL se o tipo é IS_NULL  
  • 30. Aceitando Parâmetros – Exemplo 1 PHP_FUNCTION(exemplo1) { /* 1 - Definição das variáveis */ char *nome; int nome_len; /* 2 - Pegando os parâmetros */ if (zend_parse_parameters(1 TSRMLS_CC, “s”, &nome, &nome_len) == FAILURE) { return; } /* 3 - Implementação da função... */ php_printf(“Nome: %s”, nome); /* 4 - Retorno de valor */ RETVAL_NULL; } Em PHP (User Space): <?php exemplo1(“Cássia”); ?> Resultado: Nome: Cássia    
  • 31. Aceitando Parâmetros – Exemplo 2 PHP_FUNCTION(meu_gettype) { /* 1 - Declaração das variáveis */ zval *variavel; /* 2 - Recebendo parâmetros */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &variavel) == FAILURE) { return; } /* 3 - Implementação da função */ switch (Z_TYPE_P(variavel)) { case IS_LONG: php_printf("Inteiro"); break; case IS_ARRAY: Em PHP (User Space): php_printf("Matriz"); break; <?php default: meu_gettype(array(2,2)); php_printf("Tipo desconhecido"); ?> break; } /* 4 - Retorno de valor */ Resultado: }     Matriz
  • 32. Retornando Valor – Exemplo 3 PHP_FUNCTION(numeroCao) { /* 1 - Declaração das variáveis */ /* 2 - Recebendo parâmetros */ /* 3 - Implementação da função */ /* 4 - Retorno de valor */ RETVAL_LONG(666); }    
  • 33. Definição de Classe - phpsc.c /* Arquivo phpsc.c */ zend_class_entry *phpsc_pessoa_ce; /* Declaração de métodos */ const zend_function_entry phpsc_pessoa_functions[] = { ZEND_ME(phpscPessoa, “__construct”, NULL, ZEND_ACC_PUBLIC) ZEND_ME(phpscPessoa, “getNome”, NULL, ZEND_ACC_PUBLIC) ZEND_ME(phpscPessoa, “getVersion”, NULL, ZEND_ACC_STATIC) {NULL, NULL, NULL} }; /* Declaração da classe */ PHP_MINIT_FUNCTION(EXTNAME) { zend_class_entry ce; INIT_NS_CLASS_ENTRY(ce, “phpsc”, “Pessoa”, phpsc_pessoa_functions); phpsc_pessoa_ce = zend_register_internal_class(&ce TSRMLS_CC); /* Definindo propriedades */ zend_declare_property_null(phpsc_pessoa_ce, “_nome”, sizeof(“_nome”)-1, ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_long(phpsc_pessoa_ce, “_idade”, sizeof(“_idade”)-1, ZEND_ACC_PRIVATE TSRMLS_CC); } /* Implementação dos métodos */ PHP_METHOD(phpscPessoa, __construct)...    
  • 34. Definição de Classe - phpsc.c /* Implementação dos métodos */ PHP_METHOD(phpscPessoa, __construct) { php_printf(“Construtor chamado! rá!rn”); } PHP_METHOD(phpscPessoa, getNome) { zval *nome = NULL; nome = zend_read_property(phpsc_pessoa_ce, getThis(), “_nome”, sizeof(“_nome”)-1, 0 TSRMLS_CC); RETVAL_STRING(Z_STRVAL_P(nome), 1); }    
  • 35. Definição de Classe - php_phpsc.h /* Arquivo php_phpsc.h */ /* ... */ /* Declaração dos protótipos */ PHP_METHOD(phpscPessoa, __construct); PHP_METHOD(phpscPessoa, getNome); PHP_METHOD(phpscPessoa, getVersion); /* ... */    
  • 36. Macros/Funcs OOP - Constantes int zend_declare_class_constant(zend_class_entry *ce, char *name, size_t name_len, zval *value TSRMLS_DC); int zend_declare_class_constant_long(zend_class_entry *ce, char *name, size_t name_len, long value TSRMLS_DC); int zend_declare_class_constant_bool(zend_class_entry *ce, char *name, size_t name_len, zend_bool value TSRMLS_DC); int zend_declare_class_constant_double(zend_class_entry *ce, char *name, size_t name_len, double value TSRMLS_DC); int zend_declare_class_constant_stringl(zend_class_entry *ce, char *name, size_t name_len, char *val, size_t val_len TSRMLS_DC); int zend_declare_class_constant_string(zend_class_entry *ce, char *name, size_t name_len, char *value TSRMLS_DC); Obs.: Usar sizeof para passar o argumento name_len.    
  • 37. Macros/Funcs OOP - Propriedades int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC); int zend_declare_property_null(zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC); int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC); int zend_declare_property_long(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC); int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC); int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC); zval *zend_read_property(zend_class_entry *scope, zval *object,   char *name, int name_length,  zend_bool silent TSRMLS_DC);
  • 38. Live DEMO    
  • 39. Referência Livros Advanced PHP Programming    Autor: George Schlossnagle    ISBN­10: 0672325616 Extending and Embedding PHP    Autor: Sara Golemon    ISBN#0­6723­2704­X Apresentações Marcus Börger   http://talks.somabo.de    
  • 40. die() Erick Belluci Tedeschi ­ @ericktedeschi http://oerick.com http://www.linkedin.com/in/ericktedeschi Grupo PHPBR­Internals   http://groups.google.com/group/phpbr­internals