SlideShare una empresa de Scribd logo
1 de 89
Descargar para leer sin conexión
Desenvolvendo Extensões
PECL
PHP Conference Brasil 2010
26 de novembro
Pedro Padron – ppadron@w3p.com.br - @ppadron
Hello World
- php, pear, pecl, linux, plesk, puppet...
- pecl.php.net/augeas
- spamassassin php api
- api api api api api api api api
- wordpress
Por que você está aqui?
(nesta sala, não no universo)
pecl
- php extension community library
- dizem que se lê “pickle”
- ou no brasil: “pê” “ê” (ou “é”) “cê” “éle”
Motivos para criar uma extensão
- performance
- “esconder o código” do cliente
- acessar funções de uma biblioteca C
- modificar o comportamento do PHP
acessar funções de uma biblioteca em C
"It is a glue language that glues the web
server to all the interesting backend
libraries available out there." *
Rasmus Lerdorf
* http://www.urgig.com/int/0107_rl_a_int.html
modificar o comportamento do PHP
funcall
zend extensions
- trabalham na camada da ZendEngine
- bytecode compiler
- opcode handlers
- exemplos: xdebug, test_handlers,
ZendGuardLoader
zend extensions
php extensions
não faz nada do que uma zend
extension faz
montando o ambiente de trabalho
montando o ambiente - linux
- debian/ubuntu:
apt-get install php5-dev (headers & phpize)
apt-get build-dep php5 (libs necessárias)
apt-get install php5-dbg (debug symbols)
- redhat/fedora:
yum install php5-dev
yum install yum-utils
yum-builddep php5
montando o ambiente - windows
- sim, é possível; sim, é mais chato que no linux
- visual c++ 2008 (express edition é de graça)
- microsoft platform sdk
- várias bibliotecas necessárias pelo PHP
- variáveis de ambiente no console do visual studio
- processo completo:
http://wiki.php.net/internals/windows/stepbystepbuild
código fonte do PHP
- php.net/downloads
- 5.3.3
- extraia p/ algum diretório
- em windows, não use caminhos que
contenham espaços
- cd php-src/ext
compilando a extensão - linux
$ cd ext/minhaextensao
$ phpize
$ ./configure
$ make
$ (sudo) make install
“extension=minhaextensao.so” no php.ini
compilando a extensão - windows
- siga todos os passos da etapa de setup do ambiente
- garanta que a extensão está no diretório ext/
- abra o Visual Studio Command Prompt
> vcvars32.bat
> buildconf
> configure –disable-all –enable-minhaextensao=shared
–enable-cli
> nmake
- dentro de Release_TS estará php_minhaextensao.dll
gerando o esqueleto de uma
extensão
gerando o esqueleto de uma extensão
- é tão chato que foi preciso criar um
script pra isso
- php-src/ext/ext_skel
- php-src/ext/ext_skel_win32.php
* precisa de CygWin instalado
* gera o arquivo .dsp do VisualStudio
gerando o esqueleto de uma extensão
./ext_skel –extname=minhaextensao
.cvsignore (renomeie para .gitignore =P)
config.m4 (config script linux)
config.w32 (config script windows)
CREDITS (seu nome e seu e-mail)
EXPERIMENTAL (not for use in production)
minhaextensao.c (código da extensão)
minhaextensao.php (script de teste)
php_minhaextensao.h (headers)
tests/001.phpt (primeiro teste)
minhaextensao.c – module entry
essa estrutura vai armazenar todas as
informações sobre sua extensão
minhaextensao.c - functions
Sim, a última linha tem sempre que ser {NULL, NULL, NULL}, isso indica
para a Zend Engine que a lista de funções acabou.
Internamente, confirm_minha_extensao_compiled será chamada de
zif_confirm_minhaextensao_compiled. (zif = zend internal function)
minhaextensao.c - functions
E essa é a função!
php_minhaextensao.h
extern zend_module_entry minhaextensao_module_entry;
PHP_MINIT_FUNCTION(minhaextensao);
PHP_MSHUTDOWN_FUNCTION(minhaextensao);
PHP_RINIT_FUNCTION(minhaextensao);
PHP_RSHUTDOWN_FUNCTION(minhaextensao);
PHP_MINFO_FUNCTION(minhaextensao);
PHP_FUNCTION(confirm_minhaextensao_compiled);
Declarando as funções e a definição do módulo
php_minhaextensao.h
- ZTS = Zend Thread Safety
- TSRM = Thread Safe Resource Manager
#ifdef ZTS
#include "TSRM.h"
#endif
config.m4
Se a sua extensão não usa nenhuma
biblioteca externa:
config.m4
Se a sua extensão usa alguma biblioteca externa
config.m4
Testando a biblioteca pela presença
de algum símbolo
config.m4
símbolos de uma biblioteca são todos os elementos
visíveis ao seu usuário, podem ser classes, funções,
estruturas de dados, etc...
bibliotecas externas – embutir ou linkar?
- em windows é preferível embutir a biblioteca
externa, pois o usuário final só precisa instalar
sua dll (php_minhaextensao.dll)
- em linux, verifique se as distribuições possuem
pacotes para a biblioteca em questão;
- se for embutir, verifique se a licença da
biblioteca permite isso
phpinfo(); - PHP_MINFO_FUNCTION
phpinfo(); - PHP_MINFO_FUNCTION
phpinfo(); - PHP_MINFO_FUNCTION
não abuse da criatividade
void php_info_print_table_start(void)
void php_info_print_table_end(void)
void php_info_print_table_header(int cols, ...)
void php_info_print_table_colspan_header(int cols, char *header)
void php_info_print_table_row(int cols, ...)
void php_info_print_table_row_ex(int cols, char *class, ...)
void php_info_print_box_start(int flag)
void php_info_print_box_end()
void php_info_print_hr(void)
...
PHP_MINIT_FUNCTION
- executado uma vez para cada processo
- cli/cgi/multithread sapi => executa apenas
uma vez (apache2-worker)
- sempre que houver fork(); inicia novamente
o ambiente (mod_php no apache2-prefork)
- registrar classes, constantes, configurações
php.ini...
PHP_MINIT_FUNCTION
ppadron@delorean:$ php -r 'echo MINHAEXTENSAO_HELLO;'
Hello World
PHP_RINIT_FUNCTION
- executado a cada requisição feita ao
script
- evite inicializar muita coisa aqui,
economize memória
.ini settings
- primeiro você declara as configs
- inicializa em PHP_MINIT_FUNCTION
- destrói em PHP_MINIT_SHUTDOWN
- exibe em PHP_MINFO_FUNCTION
.ini settings – declara, inicializa, destrói
.ini settings – exibindo no phpinfo();
.ini settings – acessando os valores
/* VALORES ORIGINAIS */
const char *strval = INI_ORIG_STR("minhaextensao.config");
long lval = INI_ORIG_INT("minhaextensao.config_int");
double dval = INI_ORIG_FLT("minhaextensao.config_float");
zend_bool bval = INI_ORIG_BOOL("minhaextensao.config_bool");
/* VALORES ATUAIS */
long lval = INI_INT("minhaextensao.config_int");
double dval = INI_FLT("minhaextensao.config_float");
zend_bool bval = INI_BOOL("minhaextensao.config_bool");
chega de enrolação, vamos trabalhar
quantos tipos de dados existem no
PHP?
por baixo dos panos, eles são
representados por um só: o ZVAL
struct {
union {
long lval;
double dval;
struct {
char *val;
int len;
} str;
HashTable *ht;
zend_object_value obj;
} value;
zend_uint refcount;
zend_uchar type;
zend_uchar is_ref;
} zval;
prazer, ZVAL.
preciso sempre mexer direto no
ZVAL?
a não ser que você saiba o que está
fazendo, não.
existem diversas funções e macros
para lidar com um ZVAL
arrays
PHP_FUNCTION(minhaextensao_me_da_um_array)
{
zval *meu_primeiro_array;
ALLOC_INIT_ZVAL(meu_primeiro_array);
array_init(meu_primeiro_array);
array_init(return_value);
add_next_index_null(meu_primeiro_array);
add_next_index_string(meu_primeiro_array, "ueeeba!!", 1);
/* uau */
add_next_index_zval(return_value, meu_primeiro_array);
}
arrays – minha primeira função
arrays – minha primeira função
function minhaextensao_me_da_um_array()
{
$meu_primeiro_array = array();
$retorno = array();
$meu_primeiro_array[] = null;
$meu_primeiro_array[] = “ueeeba!!”;
$retorno[] = $meu_primeiro_array;
return $retorno;
}
arrays – minha primeira função
$ php -r 'var_dump(minhaextensao_me_da_um_array());'
array(1) {
[0]=>
array(2) {
[0]=>
NULL
[1]=>
string(8) "ueeeba!!"
}
}
arrays – lista de funções
Fonte: http://devzone.zend.com/node/view/id/1022#Heading5
os outros tipos que não tem tanta graça
zval *meuzval;
ZVAL_NULL(meuzval);
ZVAL_LONG(meuzval, 1408);
/* bool usa o mesmo espaço de long */
ZVAL_BOOL(meuzval, 1);
ZVAL_STRING(meuzval, “tchananan”, 0);
daqui a pouco vamos discutir sobre
resource e objetos, guentaí
retornando valores em funções
- já vimos que existe um tal de
return_value em algum lugar
- podemos manipular seu valor e deixar
que o php o retorne
- ou podemos usar alguns atalhos
retornando valores em funções
PHP_FUNCTION(minhaextensao_bool)
{
RETURN_TRUE;
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Nunca vai chegar aqui");
}
retornando os valores em funções
RETURN_NULL();
RETURN_STRING(“bola”, 0);
RETURN_TRUE;
RETURN_FALSE;
RETURN_DOUBLE(3.14);
RETURN_LONG(1408);
e assim por diante...
agora que sabemos como retornar
valores, vamos receber valores
recebendo valores em uma função
PHP_FUNCTION(minhaextensao_recebe_string)
{
char *param;
int param_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"s", &param, &param_len) == FAILURE) {
return;
}
php_printf("Obrigado por me passar como parametro: ");
PHPWRITE(param, param_len);
php_printf("n");
}
recebendo valores em uma função
minhaextensao_recebe_string("eba!");
// Obrigado por me passar como parametro: eba!
minhaextensao_recebe_string();
// PHP Warning: minhaextensao_recebe_string()
expects exactly 1 parameter, 0 given
class bola {
public function __toString() {
return “bola”;
}
}
minhaextensao_recebe_string(new bola());
// Obrigado por me passar como parametro: bola
recebendo valores opcionais
PHP_FUNCTION(minhaextensao_recebe_string_opcional)
{
char *str = "default";
int str_len = sizeof("default") - 1;
if (zend_parse_parameters(ZEND_NUM_ARGS()
TSRMLS_CC, "|s", &str, &str_len) == FAILURE) {
RETURN_FALSE;
}
php_printf("vejam: ");
PHPWRITE(str, str_len);
php_printf("n");
}
recebendo valores opcionais
minhaextensao_recebe_string_opcional();
// vejam: default
minhaextensao_recebe_string_opcional(“bola”);
// vejam: bola
zend_parse_parameters
Fonte: http://devzone.zend.com/node/view/id/1022
resources
resources
- permite lidar com estruturas mais
complexas em C e passá-las de um lado
para o outro;
- inicializados em PHP_MINIT_FUNCTION;
- usado em extensões procedurais;
resources – inicialização/destruição
/* isso está no topo do minhaextensao.c */
static int le_minhaextensao;
static void php_minhaextensao_resource_destrutor(
zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
FILE *fp = (FILE *) rsrc->ptr;
fclose(fp);
}
PHP_MINIT_FUNCTION(minhaextensao)
{
le_minhaextensao = zend_register_list_destructors_ex(
php_minhaextensao_resource_destrutor,
NULL, "Resource da Minha Extensao",
module_number);
return SUCCESS;
}
resources – criando e retornando
PHP_FUNCTION(minhaextensao_resource)
{
FILE *fp;
fp = fopen("/tmp/arquivo", "r");
if (!fp) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Naaaaaao");
RETURN_FALSE;
}
ZEND_REGISTER_RESOURCE(return_value, fp, le_minhaextensao);
}
$ php -r 'var_dump(minhaextensao_resource());'
resource(4) of type (Resource da Minha Extensao)
resources – recebendo como parâmetro
PHP_FUNCTION(minhaextensao_resource_check)
{
FILE *fp;
zval *resource;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r",
&resource) == FAILURE) {
RETURN_NULL();
}
ZEND_FETCH_RESOURCE(fp, FILE*, &resource, -1,
"Resource da Minha Extensao", le_minhaextensao);
if (!fp) {
RETURN_FALSE;
}
RETURN_TRUE;
}
resource – recebendo como parâmetro
$resource = minhaextensao_resource();
$result = minhaextensao_resource_check($resource);
var_dump($result);
// bool(true)
$resource = curl_init();
$result = minhaextensao_resource_check($resource);
var_dump($result);
// PHP Warning: minhaextensao_resource_check(): supplied
resource is not a valid Resource da Minha Extensao resource
orientação a objetos
estudo de caso: extensão augeas
declarando uma classe
/* {{{ zend_class_entry */
zend_class_entry *augeas_ce_Augeas;
/* }}} */
/* REFLECTION! */
/* {{{ ZEND_BEGIN_ARG_INFO */
ZEND_BEGIN_ARG_INFO_EX(arginfo_Augeas__construct, 0)
ZEND_ARG_INFO(0, root)
ZEND_ARG_INFO(0, loadpath)
ZEND_ARG_INFO(0, flags)
ZEND_END_ARG_INFO();
ZEND_BEGIN_ARG_INFO(arginfo_Augeas_get, 0)
ZEND_ARG_INFO(0, path)
ZEND_END_ARG_INFO();
/* }}} */
declarando uma classe – lista de métodos
/* {{{ augeas_methods */
static zend_function_entry augeas_methods[] = {
PHP_ME(Augeas, __construct, arginfo_Augeas__construct, ZEND_ACC_PUBLIC)
PHP_ME(Augeas, get, arginfo_Augeas_get, ZEND_ACC_PUBLIC)
PHP_ME(Augeas, set, arginfo_Augeas_set, ZEND_ACC_PUBLIC)
PHP_ME(Augeas, match, arginfo_Augeas_match, ZEND_ACC_PUBLIC)
PHP_ME(Augeas, rm, arginfo_Augeas_rm, ZEND_ACC_PUBLIC)
PHP_ME(Augeas, save, arginfo_Augeas_save, ZEND_ACC_PUBLIC)
PHP_ME(Augeas, mv, arginfo_Augeas_mv, ZEND_ACC_PUBLIC)
PHP_ME(Augeas, insert, arginfo_Augeas_insert, ZEND_ACC_PUBLIC)
{ NULL, NULL, NULL }
};
/* }}} */
ZEND_ACC_PUBLIC
ZEND_ACC_PROTECTED
ZEND_ACC_PRIVATE
ZEND_ACC_STATIC
ZEND_ACC_ABSTRACT
ZEND_ACC_FINAL
declarando uma classe - inicialização
PHP_MINIT_FUNCTION(augeas)
{
zend_class_entry ce;
/* Register Augeas class */
INIT_CLASS_ENTRY(ce, "Augeas", augeas_methods);
augeas_ce_Augeas = zend_register_internal_class(&ce TSRMLS_CC);
return SUCCESS;
}
declarando uma classe – inicialização
(namespace)
PHP_MINIT_FUNCTION(augeas)
{
zend_class_entry ce;
/* Register Augeas class */
INIT_NS_CLASS_ENTRY(ce, “Augeas”, "Augeas", augeas_methods);
augeas_ce_Augeas = zend_register_internal_class(&ce TSRMLS_CC);
return SUCCESS;
}
declarando uma classe - herança
/* Register AugeasException class (inherits Exception) */
INIT_CLASS_ENTRY(ce, "AugeasException", NULL);
augeas_ce_AugeasException = zend_register_internal_class_ex(
&ce_exception, zend_exception_get_default(TSRMLS_C),
NULL TSRMLS_DC);
Declarando uma classe - 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_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);
Créditos: Erick Tedeschi
declarando uma classe - 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_string(zend_class_entry *ce,
char *name, size_t name_len, char *value TSRMLS_DC);
Créditos: Erick Tedeschi
mas... e os métodos?
quase igual funções...
AUGEAS_FROM_OBJECT ???
getThis() ???
vamos dar um tempo aqui e ir logo
para os arquivos...
estamos de volta
quer aprender mais?
compre o livro da Sara Golemon
“Extending and Embedding PHP”
leia o código alheio
http://lxr.php.net/
php cross-referenced source code
dúvidas?
obrigado =)

Más contenido relacionado

La actualidad más candente

Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014Michael Castillo Granados
 
Oficina de shell script
Oficina de shell scriptOficina de shell script
Oficina de shell scriptbrunobione
 
Programação em Shell Script
Programação em Shell ScriptProgramação em Shell Script
Programação em Shell ScriptReinaldo Lima
 
PHP na Tela Escura: Aplicações Poderosas em Linha de Comando
PHP na Tela Escura: Aplicações Poderosas em Linha de ComandoPHP na Tela Escura: Aplicações Poderosas em Linha de Comando
PHP na Tela Escura: Aplicações Poderosas em Linha de ComandoRafael Jaques
 
Perl Moderno, dia5
Perl Moderno, dia5Perl Moderno, dia5
Perl Moderno, dia5garux
 
Shell Script - Luz e trevas
Shell Script - Luz e trevasShell Script - Luz e trevas
Shell Script - Luz e trevasOsvaldo Filho
 
Programando Melhor - Flisol
Programando Melhor - FlisolProgramando Melhor - Flisol
Programando Melhor - FlisolLeonn Leite
 
Perl Moderno, dia2
Perl Moderno, dia2Perl Moderno, dia2
Perl Moderno, dia2garux
 
PHP Day - PHP para iniciantes
PHP Day - PHP para iniciantesPHP Day - PHP para iniciantes
PHP Day - PHP para iniciantesAlmir Mendes
 
Perl Moderno, dia4
Perl Moderno, dia4Perl Moderno, dia4
Perl Moderno, dia4garux
 
Perl Moderno, dia3
Perl Moderno, dia3Perl Moderno, dia3
Perl Moderno, dia3garux
 
PHP Jedi - Boas Práticas e Alta Performance
PHP Jedi - Boas Práticas e Alta PerformancePHP Jedi - Boas Práticas e Alta Performance
PHP Jedi - Boas Práticas e Alta PerformanceFelipe Ribeiro
 

La actualidad más candente (20)

Shell script
Shell scriptShell script
Shell script
 
Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014
 
Oficina de shell script
Oficina de shell scriptOficina de shell script
Oficina de shell script
 
Shell Script v0
Shell Script v0Shell Script v0
Shell Script v0
 
Programação em Shell Script
Programação em Shell ScriptProgramação em Shell Script
Programação em Shell Script
 
Shell Script
Shell ScriptShell Script
Shell Script
 
PHP na Tela Escura: Aplicações Poderosas em Linha de Comando
PHP na Tela Escura: Aplicações Poderosas em Linha de ComandoPHP na Tela Escura: Aplicações Poderosas em Linha de Comando
PHP na Tela Escura: Aplicações Poderosas em Linha de Comando
 
Curso shell
Curso shellCurso shell
Curso shell
 
Al sweigart, cap 3
Al sweigart, cap 3Al sweigart, cap 3
Al sweigart, cap 3
 
Linguagem PHP
Linguagem PHPLinguagem PHP
Linguagem PHP
 
Python 03
Python 03Python 03
Python 03
 
Perl Moderno, dia5
Perl Moderno, dia5Perl Moderno, dia5
Perl Moderno, dia5
 
Shell Script - Luz e trevas
Shell Script - Luz e trevasShell Script - Luz e trevas
Shell Script - Luz e trevas
 
Programando Melhor - Flisol
Programando Melhor - FlisolProgramando Melhor - Flisol
Programando Melhor - Flisol
 
Perl Moderno, dia2
Perl Moderno, dia2Perl Moderno, dia2
Perl Moderno, dia2
 
PHP Day - PHP para iniciantes
PHP Day - PHP para iniciantesPHP Day - PHP para iniciantes
PHP Day - PHP para iniciantes
 
Perl Moderno, dia4
Perl Moderno, dia4Perl Moderno, dia4
Perl Moderno, dia4
 
Sapo Sessions PHP
Sapo Sessions PHPSapo Sessions PHP
Sapo Sessions PHP
 
Perl Moderno, dia3
Perl Moderno, dia3Perl Moderno, dia3
Perl Moderno, dia3
 
PHP Jedi - Boas Práticas e Alta Performance
PHP Jedi - Boas Práticas e Alta PerformancePHP Jedi - Boas Práticas e Alta Performance
PHP Jedi - Boas Práticas e Alta Performance
 

Destacado

Depurando Aplicacoes PHP com XDebug e FirePHP II
Depurando Aplicacoes PHP com XDebug e FirePHP IIDepurando Aplicacoes PHP com XDebug e FirePHP II
Depurando Aplicacoes PHP com XDebug e FirePHP IIJefferson Girão
 
PHP Traits
PHP TraitsPHP Traits
PHP Traitsmattbuzz
 
PHP traits, treat or threat?
PHP traits, treat or threat?PHP traits, treat or threat?
PHP traits, treat or threat?Nick Belhomme
 
Profiling PHP with Xdebug / Webgrind
Profiling PHP with Xdebug / WebgrindProfiling PHP with Xdebug / Webgrind
Profiling PHP with Xdebug / WebgrindSam Keen
 
Debugging PHP With Xdebug
Debugging PHP With XdebugDebugging PHP With Xdebug
Debugging PHP With XdebugMark Niebergall
 

Destacado (6)

Depurando Aplicacoes PHP com XDebug e FirePHP II
Depurando Aplicacoes PHP com XDebug e FirePHP IIDepurando Aplicacoes PHP com XDebug e FirePHP II
Depurando Aplicacoes PHP com XDebug e FirePHP II
 
PHP Traits
PHP TraitsPHP Traits
PHP Traits
 
PHP traits, treat or threat?
PHP traits, treat or threat?PHP traits, treat or threat?
PHP traits, treat or threat?
 
Profiling PHP with Xdebug / Webgrind
Profiling PHP with Xdebug / WebgrindProfiling PHP with Xdebug / Webgrind
Profiling PHP with Xdebug / Webgrind
 
Debugging PHP With Xdebug
Debugging PHP With XdebugDebugging PHP With Xdebug
Debugging PHP With Xdebug
 
Advanced PHP Simplified
Advanced PHP SimplifiedAdvanced PHP Simplified
Advanced PHP Simplified
 

Similar a Desenvolvendo Extensões PHP

PHPSC Conference 2010 - Desenvolvimento de Extensões PECL
PHPSC Conference 2010 - Desenvolvimento de Extensões PECLPHPSC Conference 2010 - Desenvolvimento de Extensões PECL
PHPSC Conference 2010 - Desenvolvimento de Extensões PECLErick Belluci Tedeschi
 
PHP like a super hero
PHP like a super heroPHP like a super hero
PHP like a super heroElton Minetto
 
Introdução ao Zend Framework 2
Introdução ao Zend Framework 2Introdução ao Zend Framework 2
Introdução ao Zend Framework 2Elton Minetto
 
Desenvolvendo Sistemas de Arquivos no FUSE - Luis Otávio de Colla Furquim
Desenvolvendo Sistemas de Arquivos no FUSE - Luis Otávio de Colla FurquimDesenvolvendo Sistemas de Arquivos no FUSE - Luis Otávio de Colla Furquim
Desenvolvendo Sistemas de Arquivos no FUSE - Luis Otávio de Colla FurquimTchelinux
 
Docker API Client with PHP and PYTHON
Docker API Client with PHP and PYTHONDocker API Client with PHP and PYTHON
Docker API Client with PHP and PYTHONIago Machado
 
15 coisas sobre php para saber antes de morrer
15 coisas sobre php para saber antes de morrer15 coisas sobre php para saber antes de morrer
15 coisas sobre php para saber antes de morrerMichele Silva
 
Qualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnitQualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnitDiego Tremper
 
Linux4all#2
Linux4all#2Linux4all#2
Linux4all#2Daniel
 
PHP-CLI in 7 steps - 7Masters PHP
PHP-CLI in 7 steps - 7Masters PHPPHP-CLI in 7 steps - 7Masters PHP
PHP-CLI in 7 steps - 7Masters PHPiMasters
 
Programação Orientada a Objetos (POO) com PHP - Parte 1
Programação Orientada a Objetos (POO) com PHP - Parte 1Programação Orientada a Objetos (POO) com PHP - Parte 1
Programação Orientada a Objetos (POO) com PHP - Parte 1Israel Messias
 
Seu framework é melhor pra quê?
Seu framework é melhor pra quê?Seu framework é melhor pra quê?
Seu framework é melhor pra quê?Jaime Neto
 
Phpjedi 090307090434-phpapp01 2
Phpjedi 090307090434-phpapp01 2Phpjedi 090307090434-phpapp01 2
Phpjedi 090307090434-phpapp01 2PrinceGuru MS
 
Curso PHP - 1a. Aula (2013.2)
Curso PHP - 1a. Aula (2013.2)Curso PHP - 1a. Aula (2013.2)
Curso PHP - 1a. Aula (2013.2)Jonata Weber
 
Memcached, Gearman e Sphinx
Memcached, Gearman e SphinxMemcached, Gearman e Sphinx
Memcached, Gearman e SphinxElton Minetto
 
Introdução ao CMake
Introdução ao CMakeIntrodução ao CMake
Introdução ao CMakePaulo Remoli
 

Similar a Desenvolvendo Extensões PHP (20)

Dev Ext PHP
Dev Ext PHPDev Ext PHP
Dev Ext PHP
 
PHPSC Conference 2010 - Desenvolvimento de Extensões PECL
PHPSC Conference 2010 - Desenvolvimento de Extensões PECLPHPSC Conference 2010 - Desenvolvimento de Extensões PECL
PHPSC Conference 2010 - Desenvolvimento de Extensões PECL
 
Desenvolvimento de Extensões PECL
Desenvolvimento de Extensões PECLDesenvolvimento de Extensões PECL
Desenvolvimento de Extensões PECL
 
Linux shell
Linux shellLinux shell
Linux shell
 
PHP like a super hero
PHP like a super heroPHP like a super hero
PHP like a super hero
 
Introdução ao Zend Framework 2
Introdução ao Zend Framework 2Introdução ao Zend Framework 2
Introdução ao Zend Framework 2
 
Desenvolvendo Sistemas de Arquivos no FUSE - Luis Otávio de Colla Furquim
Desenvolvendo Sistemas de Arquivos no FUSE - Luis Otávio de Colla FurquimDesenvolvendo Sistemas de Arquivos no FUSE - Luis Otávio de Colla Furquim
Desenvolvendo Sistemas de Arquivos no FUSE - Luis Otávio de Colla Furquim
 
Docker API Client with PHP and PYTHON
Docker API Client with PHP and PYTHONDocker API Client with PHP and PYTHON
Docker API Client with PHP and PYTHON
 
15 coisas sobre php para saber antes de morrer
15 coisas sobre php para saber antes de morrer15 coisas sobre php para saber antes de morrer
15 coisas sobre php para saber antes de morrer
 
Zephir
ZephirZephir
Zephir
 
Qualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnitQualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnit
 
Linux4all#2
Linux4all#2Linux4all#2
Linux4all#2
 
PHP-CLI in 7 steps - 7Masters PHP
PHP-CLI in 7 steps - 7Masters PHPPHP-CLI in 7 steps - 7Masters PHP
PHP-CLI in 7 steps - 7Masters PHP
 
Programação Orientada a Objetos (POO) com PHP - Parte 1
Programação Orientada a Objetos (POO) com PHP - Parte 1Programação Orientada a Objetos (POO) com PHP - Parte 1
Programação Orientada a Objetos (POO) com PHP - Parte 1
 
Seu framework é melhor pra quê?
Seu framework é melhor pra quê?Seu framework é melhor pra quê?
Seu framework é melhor pra quê?
 
Phpjedi 090307090434-phpapp01 2
Phpjedi 090307090434-phpapp01 2Phpjedi 090307090434-phpapp01 2
Phpjedi 090307090434-phpapp01 2
 
Curso PHP - 1a. Aula (2013.2)
Curso PHP - 1a. Aula (2013.2)Curso PHP - 1a. Aula (2013.2)
Curso PHP - 1a. Aula (2013.2)
 
Memcached, Gearman e Sphinx
Memcached, Gearman e SphinxMemcached, Gearman e Sphinx
Memcached, Gearman e Sphinx
 
Introdução ao CMake
Introdução ao CMakeIntrodução ao CMake
Introdução ao CMake
 
Modern PHP
Modern PHPModern PHP
Modern PHP
 

Desenvolvendo Extensões PHP

  • 1. Desenvolvendo Extensões PECL PHP Conference Brasil 2010 26 de novembro Pedro Padron – ppadron@w3p.com.br - @ppadron
  • 2. Hello World - php, pear, pecl, linux, plesk, puppet... - pecl.php.net/augeas - spamassassin php api - api api api api api api api api - wordpress
  • 3. Por que você está aqui? (nesta sala, não no universo)
  • 4. pecl - php extension community library - dizem que se lê “pickle” - ou no brasil: “pê” “ê” (ou “é”) “cê” “éle”
  • 5. Motivos para criar uma extensão - performance - “esconder o código” do cliente - acessar funções de uma biblioteca C - modificar o comportamento do PHP
  • 6. acessar funções de uma biblioteca em C "It is a glue language that glues the web server to all the interesting backend libraries available out there." * Rasmus Lerdorf * http://www.urgig.com/int/0107_rl_a_int.html
  • 7. modificar o comportamento do PHP funcall
  • 8. zend extensions - trabalham na camada da ZendEngine - bytecode compiler - opcode handlers - exemplos: xdebug, test_handlers, ZendGuardLoader
  • 10. php extensions não faz nada do que uma zend extension faz
  • 11. montando o ambiente de trabalho
  • 12. montando o ambiente - linux - debian/ubuntu: apt-get install php5-dev (headers & phpize) apt-get build-dep php5 (libs necessárias) apt-get install php5-dbg (debug symbols) - redhat/fedora: yum install php5-dev yum install yum-utils yum-builddep php5
  • 13. montando o ambiente - windows - sim, é possível; sim, é mais chato que no linux - visual c++ 2008 (express edition é de graça) - microsoft platform sdk - várias bibliotecas necessárias pelo PHP - variáveis de ambiente no console do visual studio - processo completo: http://wiki.php.net/internals/windows/stepbystepbuild
  • 14. código fonte do PHP - php.net/downloads - 5.3.3 - extraia p/ algum diretório - em windows, não use caminhos que contenham espaços - cd php-src/ext
  • 15. compilando a extensão - linux $ cd ext/minhaextensao $ phpize $ ./configure $ make $ (sudo) make install “extension=minhaextensao.so” no php.ini
  • 16. compilando a extensão - windows - siga todos os passos da etapa de setup do ambiente - garanta que a extensão está no diretório ext/ - abra o Visual Studio Command Prompt > vcvars32.bat > buildconf > configure –disable-all –enable-minhaextensao=shared –enable-cli > nmake - dentro de Release_TS estará php_minhaextensao.dll
  • 17. gerando o esqueleto de uma extensão
  • 18. gerando o esqueleto de uma extensão - é tão chato que foi preciso criar um script pra isso - php-src/ext/ext_skel - php-src/ext/ext_skel_win32.php * precisa de CygWin instalado * gera o arquivo .dsp do VisualStudio
  • 19. gerando o esqueleto de uma extensão ./ext_skel –extname=minhaextensao .cvsignore (renomeie para .gitignore =P) config.m4 (config script linux) config.w32 (config script windows) CREDITS (seu nome e seu e-mail) EXPERIMENTAL (not for use in production) minhaextensao.c (código da extensão) minhaextensao.php (script de teste) php_minhaextensao.h (headers) tests/001.phpt (primeiro teste)
  • 20. minhaextensao.c – module entry essa estrutura vai armazenar todas as informações sobre sua extensão
  • 21. minhaextensao.c - functions Sim, a última linha tem sempre que ser {NULL, NULL, NULL}, isso indica para a Zend Engine que a lista de funções acabou. Internamente, confirm_minha_extensao_compiled será chamada de zif_confirm_minhaextensao_compiled. (zif = zend internal function)
  • 22. minhaextensao.c - functions E essa é a função!
  • 24. php_minhaextensao.h - ZTS = Zend Thread Safety - TSRM = Thread Safe Resource Manager #ifdef ZTS #include "TSRM.h" #endif
  • 25. config.m4 Se a sua extensão não usa nenhuma biblioteca externa:
  • 26. config.m4 Se a sua extensão usa alguma biblioteca externa
  • 27. config.m4 Testando a biblioteca pela presença de algum símbolo
  • 28. config.m4 símbolos de uma biblioteca são todos os elementos visíveis ao seu usuário, podem ser classes, funções, estruturas de dados, etc...
  • 29. bibliotecas externas – embutir ou linkar? - em windows é preferível embutir a biblioteca externa, pois o usuário final só precisa instalar sua dll (php_minhaextensao.dll) - em linux, verifique se as distribuições possuem pacotes para a biblioteca em questão; - se for embutir, verifique se a licença da biblioteca permite isso
  • 32. phpinfo(); - PHP_MINFO_FUNCTION não abuse da criatividade void php_info_print_table_start(void) void php_info_print_table_end(void) void php_info_print_table_header(int cols, ...) void php_info_print_table_colspan_header(int cols, char *header) void php_info_print_table_row(int cols, ...) void php_info_print_table_row_ex(int cols, char *class, ...) void php_info_print_box_start(int flag) void php_info_print_box_end() void php_info_print_hr(void) ...
  • 33. PHP_MINIT_FUNCTION - executado uma vez para cada processo - cli/cgi/multithread sapi => executa apenas uma vez (apache2-worker) - sempre que houver fork(); inicia novamente o ambiente (mod_php no apache2-prefork) - registrar classes, constantes, configurações php.ini...
  • 34. PHP_MINIT_FUNCTION ppadron@delorean:$ php -r 'echo MINHAEXTENSAO_HELLO;' Hello World
  • 35. PHP_RINIT_FUNCTION - executado a cada requisição feita ao script - evite inicializar muita coisa aqui, economize memória
  • 36. .ini settings - primeiro você declara as configs - inicializa em PHP_MINIT_FUNCTION - destrói em PHP_MINIT_SHUTDOWN - exibe em PHP_MINFO_FUNCTION
  • 37. .ini settings – declara, inicializa, destrói
  • 38. .ini settings – exibindo no phpinfo();
  • 39. .ini settings – acessando os valores /* VALORES ORIGINAIS */ const char *strval = INI_ORIG_STR("minhaextensao.config"); long lval = INI_ORIG_INT("minhaextensao.config_int"); double dval = INI_ORIG_FLT("minhaextensao.config_float"); zend_bool bval = INI_ORIG_BOOL("minhaextensao.config_bool"); /* VALORES ATUAIS */ long lval = INI_INT("minhaextensao.config_int"); double dval = INI_FLT("minhaextensao.config_float"); zend_bool bval = INI_BOOL("minhaextensao.config_bool");
  • 40. chega de enrolação, vamos trabalhar
  • 41. quantos tipos de dados existem no PHP?
  • 42. por baixo dos panos, eles são representados por um só: o ZVAL
  • 43. struct { union { long lval; double dval; struct { char *val; int len; } str; HashTable *ht; zend_object_value obj; } value; zend_uint refcount; zend_uchar type; zend_uchar is_ref; } zval; prazer, ZVAL.
  • 44. preciso sempre mexer direto no ZVAL?
  • 45. a não ser que você saiba o que está fazendo, não.
  • 46. existem diversas funções e macros para lidar com um ZVAL
  • 49. arrays – minha primeira função function minhaextensao_me_da_um_array() { $meu_primeiro_array = array(); $retorno = array(); $meu_primeiro_array[] = null; $meu_primeiro_array[] = “ueeeba!!”; $retorno[] = $meu_primeiro_array; return $retorno; }
  • 50. arrays – minha primeira função $ php -r 'var_dump(minhaextensao_me_da_um_array());' array(1) { [0]=> array(2) { [0]=> NULL [1]=> string(8) "ueeeba!!" } }
  • 51. arrays – lista de funções Fonte: http://devzone.zend.com/node/view/id/1022#Heading5
  • 52. os outros tipos que não tem tanta graça zval *meuzval; ZVAL_NULL(meuzval); ZVAL_LONG(meuzval, 1408); /* bool usa o mesmo espaço de long */ ZVAL_BOOL(meuzval, 1); ZVAL_STRING(meuzval, “tchananan”, 0);
  • 53. daqui a pouco vamos discutir sobre resource e objetos, guentaí
  • 54. retornando valores em funções - já vimos que existe um tal de return_value em algum lugar - podemos manipular seu valor e deixar que o php o retorne - ou podemos usar alguns atalhos
  • 55. retornando valores em funções PHP_FUNCTION(minhaextensao_bool) { RETURN_TRUE; php_error_docref(NULL TSRMLS_CC, E_WARNING, "Nunca vai chegar aqui"); }
  • 56. retornando os valores em funções RETURN_NULL(); RETURN_STRING(“bola”, 0); RETURN_TRUE; RETURN_FALSE; RETURN_DOUBLE(3.14); RETURN_LONG(1408); e assim por diante...
  • 57. agora que sabemos como retornar valores, vamos receber valores
  • 58. recebendo valores em uma função PHP_FUNCTION(minhaextensao_recebe_string) { char *param; int param_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &param, &param_len) == FAILURE) { return; } php_printf("Obrigado por me passar como parametro: "); PHPWRITE(param, param_len); php_printf("n"); }
  • 59. recebendo valores em uma função minhaextensao_recebe_string("eba!"); // Obrigado por me passar como parametro: eba! minhaextensao_recebe_string(); // PHP Warning: minhaextensao_recebe_string() expects exactly 1 parameter, 0 given class bola { public function __toString() { return “bola”; } } minhaextensao_recebe_string(new bola()); // Obrigado por me passar como parametro: bola
  • 60. recebendo valores opcionais PHP_FUNCTION(minhaextensao_recebe_string_opcional) { char *str = "default"; int str_len = sizeof("default") - 1; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &str, &str_len) == FAILURE) { RETURN_FALSE; } php_printf("vejam: "); PHPWRITE(str, str_len); php_printf("n"); }
  • 61. recebendo valores opcionais minhaextensao_recebe_string_opcional(); // vejam: default minhaextensao_recebe_string_opcional(“bola”); // vejam: bola
  • 64. resources - permite lidar com estruturas mais complexas em C e passá-las de um lado para o outro; - inicializados em PHP_MINIT_FUNCTION; - usado em extensões procedurais;
  • 65. resources – inicialização/destruição /* isso está no topo do minhaextensao.c */ static int le_minhaextensao; static void php_minhaextensao_resource_destrutor( zend_rsrc_list_entry *rsrc TSRMLS_DC) { FILE *fp = (FILE *) rsrc->ptr; fclose(fp); } PHP_MINIT_FUNCTION(minhaextensao) { le_minhaextensao = zend_register_list_destructors_ex( php_minhaextensao_resource_destrutor, NULL, "Resource da Minha Extensao", module_number); return SUCCESS; }
  • 66. resources – criando e retornando PHP_FUNCTION(minhaextensao_resource) { FILE *fp; fp = fopen("/tmp/arquivo", "r"); if (!fp) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Naaaaaao"); RETURN_FALSE; } ZEND_REGISTER_RESOURCE(return_value, fp, le_minhaextensao); } $ php -r 'var_dump(minhaextensao_resource());' resource(4) of type (Resource da Minha Extensao)
  • 67. resources – recebendo como parâmetro PHP_FUNCTION(minhaextensao_resource_check) { FILE *fp; zval *resource; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &resource) == FAILURE) { RETURN_NULL(); } ZEND_FETCH_RESOURCE(fp, FILE*, &resource, -1, "Resource da Minha Extensao", le_minhaextensao); if (!fp) { RETURN_FALSE; } RETURN_TRUE; }
  • 68. resource – recebendo como parâmetro $resource = minhaextensao_resource(); $result = minhaextensao_resource_check($resource); var_dump($result); // bool(true) $resource = curl_init(); $result = minhaextensao_resource_check($resource); var_dump($result); // PHP Warning: minhaextensao_resource_check(): supplied resource is not a valid Resource da Minha Extensao resource
  • 70. estudo de caso: extensão augeas
  • 71. declarando uma classe /* {{{ zend_class_entry */ zend_class_entry *augeas_ce_Augeas; /* }}} */ /* REFLECTION! */ /* {{{ ZEND_BEGIN_ARG_INFO */ ZEND_BEGIN_ARG_INFO_EX(arginfo_Augeas__construct, 0) ZEND_ARG_INFO(0, root) ZEND_ARG_INFO(0, loadpath) ZEND_ARG_INFO(0, flags) ZEND_END_ARG_INFO(); ZEND_BEGIN_ARG_INFO(arginfo_Augeas_get, 0) ZEND_ARG_INFO(0, path) ZEND_END_ARG_INFO(); /* }}} */
  • 72. declarando uma classe – lista de métodos /* {{{ augeas_methods */ static zend_function_entry augeas_methods[] = { PHP_ME(Augeas, __construct, arginfo_Augeas__construct, ZEND_ACC_PUBLIC) PHP_ME(Augeas, get, arginfo_Augeas_get, ZEND_ACC_PUBLIC) PHP_ME(Augeas, set, arginfo_Augeas_set, ZEND_ACC_PUBLIC) PHP_ME(Augeas, match, arginfo_Augeas_match, ZEND_ACC_PUBLIC) PHP_ME(Augeas, rm, arginfo_Augeas_rm, ZEND_ACC_PUBLIC) PHP_ME(Augeas, save, arginfo_Augeas_save, ZEND_ACC_PUBLIC) PHP_ME(Augeas, mv, arginfo_Augeas_mv, ZEND_ACC_PUBLIC) PHP_ME(Augeas, insert, arginfo_Augeas_insert, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; /* }}} */ ZEND_ACC_PUBLIC ZEND_ACC_PROTECTED ZEND_ACC_PRIVATE ZEND_ACC_STATIC ZEND_ACC_ABSTRACT ZEND_ACC_FINAL
  • 73. declarando uma classe - inicialização PHP_MINIT_FUNCTION(augeas) { zend_class_entry ce; /* Register Augeas class */ INIT_CLASS_ENTRY(ce, "Augeas", augeas_methods); augeas_ce_Augeas = zend_register_internal_class(&ce TSRMLS_CC); return SUCCESS; }
  • 74. declarando uma classe – inicialização (namespace) PHP_MINIT_FUNCTION(augeas) { zend_class_entry ce; /* Register Augeas class */ INIT_NS_CLASS_ENTRY(ce, “Augeas”, "Augeas", augeas_methods); augeas_ce_Augeas = zend_register_internal_class(&ce TSRMLS_CC); return SUCCESS; }
  • 75. declarando uma classe - herança /* Register AugeasException class (inherits Exception) */ INIT_CLASS_ENTRY(ce, "AugeasException", NULL); augeas_ce_AugeasException = zend_register_internal_class_ex( &ce_exception, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_DC);
  • 76. Declarando uma classe - 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_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); Créditos: Erick Tedeschi
  • 77. declarando uma classe - 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_string(zend_class_entry *ce, char *name, size_t name_len, char *value TSRMLS_DC); Créditos: Erick Tedeschi
  • 78. mas... e os métodos?
  • 80.
  • 82. vamos dar um tempo aqui e ir logo para os arquivos...
  • 85. compre o livro da Sara Golemon “Extending and Embedding PHP”
  • 86. leia o código alheio