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

Desenvolvendo Extensões PECL

  • 1.
    Desenvolvendo Extensões PECL PHP ConferenceBrasil 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 extensioncommunity library - dizem que se lê “pickle” - ou no brasil: “pê” “ê” (ou “é”) “cê” “éle”
  • 5.
    Motivos para criaruma 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 deuma 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.
  • 8.
    zend extensions - trabalhamna camada da ZendEngine - bytecode compiler - opcode handlers - exemplos: xdebug, test_handlers, ZendGuardLoader
  • 9.
  • 10.
    php extensions não faznada do que uma zend extension faz
  • 11.
  • 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 doPHP - 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 esqueletode uma extensão
  • 18.
    gerando o esqueletode 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 esqueletode 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 – moduleentry 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 Eessa é a função!
  • 23.
  • 24.
    php_minhaextensao.h - ZTS =Zend Thread Safety - TSRM = Thread Safe Resource Manager #ifdef ZTS #include "TSRM.h" #endif
  • 25.
    config.m4 Se a suaextensão não usa nenhuma biblioteca externa:
  • 26.
    config.m4 Se a suaextensão usa alguma biblioteca externa
  • 27.
    config.m4 Testando a bibliotecapela presença de algum símbolo
  • 28.
    config.m4 símbolos de umabiblioteca 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
  • 30.
  • 31.
  • 32.
    phpinfo(); - PHP_MINFO_FUNCTION nãoabuse 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 umavez 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 acada requisição feita ao script - evite inicializar muita coisa aqui, economize memória
  • 36.
    .ini settings - primeirovocê 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 dedados existem no PHP?
  • 42.
    por baixo dospanos, eles são representados por um só: o ZVAL
  • 43.
    struct { union { longlval; 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 mexerdireto no ZVAL?
  • 45.
    a não serque você saiba o que está fazendo, não.
  • 46.
    existem diversas funçõese macros para lidar com um ZVAL
  • 47.
  • 48.
  • 49.
    arrays – minhaprimeira 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 – minhaprimeira função $ php -r 'var_dump(minhaextensao_me_da_um_array());' array(1) { [0]=> array(2) { [0]=> NULL [1]=> string(8) "ueeeba!!" } }
  • 51.
    arrays – listade funções Fonte: http://devzone.zend.com/node/view/id/1022#Heading5
  • 52.
    os outros tiposque 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 poucovamos discutir sobre resource e objetos, guentaí
  • 54.
    retornando valores emfunçõ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 emfunções PHP_FUNCTION(minhaextensao_bool) { RETURN_TRUE; php_error_docref(NULL TSRMLS_CC, E_WARNING, "Nunca vai chegar aqui"); }
  • 56.
    retornando os valoresem 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 sabemoscomo retornar valores, vamos receber valores
  • 58.
    recebendo valores emuma 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 emuma 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
  • 62.
  • 63.
  • 64.
    resources - permite lidarcom 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 – criandoe 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 – recebendocomo 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 – recebendocomo 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
  • 69.
  • 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 osmétodos?
  • 79.
  • 81.
  • 82.
    vamos dar umtempo aqui e ir logo para os arquivos...
  • 83.
  • 84.
  • 85.
    compre o livroda Sara Golemon “Extending and Embedding PHP”
  • 86.
  • 87.
  • 88.
  • 89.