SlideShare uma empresa Scribd logo
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

Declarando as funções e a definição do módulo

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);
php_minhaextensao.h

#ifdef ZTS
#include "TSRM.h"
#endif




  - ZTS = Zend Thread Safety

  - TSRM = Thread Safe Resource Manager
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


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


              não abuse da criatividade
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
prazer, 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;
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
arrays – minha primeira função


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



 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_STATIC
    ZEND_ACC_PROTECTED                         ZEND_ACC_ABSTRACT
    ZEND_ACC_PRIVATE                           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...
Dev Ext PHP
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 =)

Mais conteúdo relacionado

PDF
Desenvolvendo Extensões PECL
PDF
Desenvolvimento de Extensões PECL
PDF
Código legado - PHP Conference Brasil - 2014
ODP
Introducao ao Shell Script
PDF
Doctrine2 Seminário PHP
ODP
Dependency injection
Desenvolvendo Extensões PECL
Desenvolvimento de Extensões PECL
Código legado - PHP Conference Brasil - 2014
Introducao ao Shell Script
Doctrine2 Seminário PHP
Dependency injection

Mais procurados (20)

PDF
Shell script
PDF
Minicurso Shell Script
PDF
Introdução ao Shell Script (versão estendida)
PDF
Tutorial Shell Script
ODP
Sapo Sessions PHP
PPTX
Curso Desenvolvimento WEB com PHP - PHP (parte 1)
PDF
Curso Gratuito de Shell Script
PDF
PHP Jedi - Boas Práticas e Alta Performance
PDF
12 aula - shell script-2015
KEY
Python 03
PDF
Linguagem PHP
PDF
Introdução às Redes Neurais com PHP
KEY
Python 02
PDF
Perl Moderno, dia5
PPT
Aula4
PPS
Shell script
PDF
Introdução à Shellscript
KEY
Python 04
PPTX
Introdução ao PHP - Criação de sites II
Shell script
Minicurso Shell Script
Introdução ao Shell Script (versão estendida)
Tutorial Shell Script
Sapo Sessions PHP
Curso Desenvolvimento WEB com PHP - PHP (parte 1)
Curso Gratuito de Shell Script
PHP Jedi - Boas Práticas e Alta Performance
12 aula - shell script-2015
Python 03
Linguagem PHP
Introdução às Redes Neurais com PHP
Python 02
Perl Moderno, dia5
Aula4
Shell script
Introdução à Shellscript
Python 04
Introdução ao PHP - Criação de sites II
Anúncio

Semelhante a Dev Ext PHP (20)

PDF
PHPSC Conference 2010 - Desenvolvimento de Extensões PECL
PDF
PHP - Uma Pequena Introducao
PDF
PHP 5.3 - Introdução
PDF
PHP Experience 2016 - [Palestra] Rumo à Certificação PHP
PDF
Apostila básica de PHP
PDF
Apostila php
PDF
Introducao ao PHP @edgarsandi
PPT
PHP GERAL
PPT
Aprofunde se no php 5.3
PPS
CURSO DE PHP PARA INICIANTES - AULA 1
PDF
PHP fora da Web
PDF
PHP like a super hero
PPTX
PHP 7 - A Maioridade do PHP
PDF
Desfrutando os Componentes do Zend Framework
PDF
Muito prazer, eu sou PHP
PDF
Muito prazer, eu sou PHP
PPTX
Curso PHP - 1a. Aula (2013.2)
PDF
PHP Experience 2016 - [Palestra] Keynote: PHP-7
PDF
PHP - Introdução
PDF
PHP para aplicações Web de grande porte
PHPSC Conference 2010 - Desenvolvimento de Extensões PECL
PHP - Uma Pequena Introducao
PHP 5.3 - Introdução
PHP Experience 2016 - [Palestra] Rumo à Certificação PHP
Apostila básica de PHP
Apostila php
Introducao ao PHP @edgarsandi
PHP GERAL
Aprofunde se no php 5.3
CURSO DE PHP PARA INICIANTES - AULA 1
PHP fora da Web
PHP like a super hero
PHP 7 - A Maioridade do PHP
Desfrutando os Componentes do Zend Framework
Muito prazer, eu sou PHP
Muito prazer, eu sou PHP
Curso PHP - 1a. Aula (2013.2)
PHP Experience 2016 - [Palestra] Keynote: PHP-7
PHP - Introdução
PHP para aplicações Web de grande porte
Anúncio

Último (19)

PDF
Fullfilment AI - Forum ecommerce 2025 // Distrito e Total Express
PDF
Aula04-Academia Heri- Tecnologia Geral 2025
PPTX
Como-se-implementa-um-softwareeeeeeeeeeeeeeeeeeeeeeeee.pptx
PPTX
Programação - Linguagem C - Variáveis, Palavras Reservadas, tipos de dados, c...
PDF
Processos na gestão de transportes, TM100 Col18
PDF
Gestão de transportes básica no SAP S/4HANA, S4611 Col20
PDF
Apple Pippin Uma breve introdução. - David Glotz
PDF
Custos e faturamento no SAP S/4HANA Transportation Management, S4TM3 Col26
PPTX
Aula16ManipulaçãoDadosssssssssssssssssssssssssssss
PPTX
Gestao-de-Bugs-em-Software-Introducao.pptxxxxxxxx
PDF
20250805_ServiceNow e a Arquitetura Orientada a Serviços (SOA) A Base para Ap...
PDF
COBITxITIL-Entenda as diferença em uso governança TI
PPTX
Aula 18 - Manipulacao De Arquivos python
PDF
Fundamentos de gerenciamento de ordens e planejamento no SAP TransportationMa...
PDF
Otimizador de planejamento e execução no SAP Transportation Management, TM120...
PDF
Custos e liquidação no SAP Transportation Management, TM130 Col18
PPTX
Informática Aplicada Informática Aplicada Plano de Ensino - estudo de caso NR...
PPTX
BANCO DE DADOS - AULAS INICIAIS-sgbd.pptx
PDF
Mergulho profundo técnico para gestão de transportes no SAP S/4HANA, S4TM6 Col14
Fullfilment AI - Forum ecommerce 2025 // Distrito e Total Express
Aula04-Academia Heri- Tecnologia Geral 2025
Como-se-implementa-um-softwareeeeeeeeeeeeeeeeeeeeeeeee.pptx
Programação - Linguagem C - Variáveis, Palavras Reservadas, tipos de dados, c...
Processos na gestão de transportes, TM100 Col18
Gestão de transportes básica no SAP S/4HANA, S4611 Col20
Apple Pippin Uma breve introdução. - David Glotz
Custos e faturamento no SAP S/4HANA Transportation Management, S4TM3 Col26
Aula16ManipulaçãoDadosssssssssssssssssssssssssssss
Gestao-de-Bugs-em-Software-Introducao.pptxxxxxxxx
20250805_ServiceNow e a Arquitetura Orientada a Serviços (SOA) A Base para Ap...
COBITxITIL-Entenda as diferença em uso governança TI
Aula 18 - Manipulacao De Arquivos python
Fundamentos de gerenciamento de ordens e planejamento no SAP TransportationMa...
Otimizador de planejamento e execução no SAP Transportation Management, TM120...
Custos e liquidação no SAP Transportation Management, TM130 Col18
Informática Aplicada Informática Aplicada Plano de Ensino - estudo de caso NR...
BANCO DE DADOS - AULAS INICIAIS-sgbd.pptx
Mergulho profundo técnico para gestão de transportes no SAP S/4HANA, S4TM6 Col14

Dev Ext 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!
  • 23. php_minhaextensao.h Declarando as funções e a definição do módulo 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);
  • 24. php_minhaextensao.h #ifdef ZTS #include "TSRM.h" #endif - ZTS = Zend Thread Safety - TSRM = Thread Safe Resource Manager
  • 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 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) ... não abuse da criatividade
  • 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. prazer, 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;
  • 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
  • 48. arrays – minha primeira função 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); }
  • 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_STATIC ZEND_ACC_PROTECTED ZEND_ACC_ABSTRACT ZEND_ACC_PRIVATE 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?
  • 81. AUGEAS_FROM_OBJECT ??? getThis() ???
  • 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