PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

40
 Desenvolvimento de extensões PECL Erick Belluci Tedeschi - @ericktedeschi PHPSC Conference 2010

Transcript of PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

Page 1: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

Desenvolvimento de extensões PECL

Erick Belluci Tedeschi - @ericktedeschi

PHPSC Conference 2010

Page 2: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

Page 3: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

Page 4: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

O que é PECL?

PHP Extension and Application Repository

Page 5: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

O que é PECL?

PHP Extension and Application Repository

PHP Extension Community Library

Page 6: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

PHP Extension and Application Repository

PHP Extension Community Library

O que é PECL?

 ← Escrito em PHP

 ← Escrito em “C”

Page 7: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

Motivação!!! heee

Aumento de performance

Adicionar novas funcionalidades

Embarcar PHP

Page 8: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

PHP Page Life Cycle

Processo do Apache

LoadModule php5_module

mysql,sockets,curl,curses,etc...

MINIT

RINIT

Script Execution

RSHUTDOWN

MSHUTDOWN

Inicia WebServer

Carrega módulo do PHP

PHP Carrega suas extensões (built­in e php.ini)

Carrega constantes, ini entries, resources, etc...

Inicializa autoglobals, symbol table, log, etc...

Libera memória...

Libera memória... (ini entries, resources, etc...)

Ciclo de vida de uma requisição de página (script) PHP originada de um WebServer:

Page 9: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

Estrutura ZVAL

typedef struct _zval_struct { zvalue_value value; zend_uint refcont; zend_uchar type; zend_uchar is_ref;} zval;

typedef union _zvalue_value { long lval; // Long,Bool,Resource double dval; // Double struct { char *val; long length; } str; // String HashTable *ht; // Array zend_object_value obj; // Object} zvalue_value;

IS_NULLIS_BOOLIS_LONGIS_DOUBLEIS_STRINGIS_ARRAYIS_OBJECTIS_RESOURCE

Page 10: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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 serInstalada: Libcurses­dev, libxml­dev, etc...

Page 11: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

Page 12: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

Esqueleto da Extensão – Arquivos

Page 13: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

Script: ext_skel

fulano@machine:/home/dev/php-5.3/ext$ ./ext_skel –extname=phpscfulano@machine:/home/dev/php-5.3/ext$ cd phpscfulano@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.phpdrwxr-xr-x 2 kirex kirex 4,0K 2010-08-28 10:25 tests

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.

Page 14: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

Page 15: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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.

Page 16: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

Page 17: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

Esqueleto da Extensão - EXTNAME.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

Estrutura do arquivo “.c”:

Page 18: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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 | | [email protected] 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 $ */

Page 19: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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"

Page 20: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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 */}

Page 21: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

}

Esqueleto da Extensão - MINFO

Page 22: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

Esqueleto da Extensão - MINIT/MSHUTDOWN

PHP_MINIT_FUNCTION(extname){

REGISTER_INI_ENTRIES();return SUCCESS;

}

PHP_MSHUTDOWN_FUNCTION(extname){

UNREGISTER_INI_ENTRIES();return SUCCESS;

}

Page 23: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

PHP_RINIT_FUNCTION(extname){

return SUCCESS;}

PHP_RSHUTDOWN_FUNCTION(extname){

return SUCCESS;}

Esqueleto da Extensão - RINIT/RSHUTDOWN

Page 24: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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[] */

};

Page 25: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

#endifSTANDARD_MODULE_PROPERTIES

};

Page 26: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

Page 27: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

API ZEND – Manipulação Arrays

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

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}

Page 28: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

Page 29: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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 determinadas String char **, int * Sempre recebe string e tamanhor resource zval **z zval zval **Z zval-ref zval ***

| Restante (parte direita) são opcionais! Proximo parametro retorna NULL se o tipo é IS_NULL

Page 30: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

Page 31: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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: php_printf("Matriz"); break; default: php_printf("Tipo desconhecido"); break; } /* 4 - Retorno de valor */}

Em PHP (User Space):

<?phpmeu_gettype(array(2,2));?>

Resultado:

Matriz

Page 32: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

Page 33: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

Page 34: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

Definição de Classe - phpsc.c

/* Implementação dos métodos */PHP_METHOD(phpscPessoa, __construct){ php_printf(“Construtor chamado! rá!\r\n”);}

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

Page 35: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

/* ... */

Page 36: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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.

Page 37: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

Page 38: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

Live DEMO

Page 39: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

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

Page 40: PHPSC Conference 2010 - Desenvolvimento de Extensões PECL

   

die()

Erick Belluci Tedeschi ­ @ericktedeschi

http://oerick.comhttp://www.linkedin.com/in/ericktedeschi

Grupo PHPBR­Internalshttp://groups.google.com/group/phpbr­internals