SlideShare a Scribd company logo
1 of 64
Premiers pas dans les
   extensions PHP
   Pierrick Charron, Confoo, Mars 2011

            pierrick@php.net
Qui suis-je ?

●   Consultant TI à Montréal
●   Auteur de l'extension PHP Stomp
●   Contributeur PHP depuis 2009
      ●   Core
      ●   RFC (Request For Comment)
      ●   Documentation (Fr & En)




Premiers pas dans les extensions - Pierrick Charron   2
Une extension ?




Premiers pas dans les extensions - Pierrick Charron    3
Pourquoi créer une extension ?
●   Permettre l'utilisation d'une librairie externe
      ●   Exemple : mysql, curl
●   Améliorer les performances
●   Opération impossible dans l'espace utilisateur
      ●   Exemple : Xdebug, operator, vld

●   Satisfaire sa curiosité




Premiers pas dans les extensions - Pierrick Charron   4
Avant de commencer
●   Présentation basée sur PHP >= 5.3
●   Utilisation de Linux

 #include <stdio.h>                                   $ echo "terminal linux"
 void main() {                                        terminal linux
    printf("C Code");
 }




Premiers pas dans les extensions - Pierrick Charron                             5
Prérequis
●   Familier avec PHP
      ●   Configuration de PHP
      ●   Installation de modules
●   Connaissances en C
●   Patience
      ●   API très complet
      ●   Beaucoup, beaucoup, beaucoup... de macros




Premiers pas dans les extensions - Pierrick Charron   6
Architecture de PHP
                                           API Serveur (SAPI)

                Apache             FPM                CLI       Embed        ...




                         Zend Engine                              PHP Core




                                        API pour les extensions

               standard           mysqli              curl      date         ...




Premiers pas dans les extensions - Pierrick Charron                                7
Cycle de vie d'une extension
●   Différentes étapes
      ●   MINIT : Initialisation du module
      ●   RINIT : Initialisation de la requête
      ●   RSHUTDOWN : Arrêt de la requête
      ●   MSHUTDOWN : Arrêt du module
●   Moment et nombre d'appels dépend du SAPI




Premiers pas dans les extensions - Pierrick Charron   8
Cycle de vie : CLI

$ php monscript.php
                                                  MINIT

                                                  RINIT

                                        Execution du script

                                            RSHUTDOWN

                                            MSHUTDOWN




Premiers pas dans les extensions - Pierrick Charron           9
Cycle de vie : Multiprocess
                     MINIT                                 MINIT

                       RINIT                                RINIT

              Execution du Script                     Execution du Script

                 RSHUTDOWN                              RSHUTDOWN


                       RINIT                                RINIT

              Execution du Script                     Execution du Script

                 RSHUTDOWN                              RSHUTDOWN

               MSHUTDOWN                               MSHUTDOWN




Premiers pas dans les extensions - Pierrick Charron                         10
Cycle de vie : Multithreaded
                                                      MINIT

                       RINIT                                        RINIT

              Execution du Script                             Execution du Script

                 RSHUTDOWN                                      RSHUTDOWN


                       RINIT                                        RINIT

              Execution du Script                             Execution du Script

                 RSHUTDOWN                                      RSHUTDOWN

                                              MSHUTDOWN




Premiers pas dans les extensions - Pierrick Charron                                 11
Zend Thread Safety / TSRM
●   Utilisé avec des "threaded webservers"
●   Chaque thread a son propre stockage local
      ●   Evite les accès concurrents




Premiers pas dans les extensions - Pierrick Charron   12
Les macros ZTS

 #define TSRMLS_D
 #define TSRMLS_D                            void ***tsrmls
                                              void ***tsrmls
 #define TSRMLS_DC
 #define TSRMLS_DC                           ,, TSRMLS_D
                                                TSRMLS_D
 #define TSRMLS_C
 #define TSRMLS_C                            tsrmls
                                              tsrmls
 #define TSRMLS_CC
 #define TSRMLS_CC                           ,, TSRMLS_C
                                                TSRMLS_C


 static void ma_fonction(int ii TSRMLS_DC);
 static void ma_fonction(int TSRMLS_DC);
 ma_function(10 TSRMLS_CC);
 ma_function(10 TSRMLS_CC);



 static void ma_fonction(int i);
 static void ma_fonction(int i);               static void ma_fonction(int i, void ***tsrmls);
                                               static void ma_fonction(int i, void ***tsrmls);
 ma_function(10);
 ma_function(10);                              ma_function(10, tsrmls);
                                               ma_function(10, tsrmls);



Premiers pas dans les extensions - Pierrick Charron                                              13
Zend Value




Premiers pas dans les extensions - Pierrick Charron    14
ZVAL
●   Zval : valeur dans espace utilisateur
      ●   Attention valeur != variable

●   Conversion de type
●   Compteur de référence




Premiers pas dans les extensions - Pierrick Charron   15
ZVAL
typedef struct _zval_struct {
typedef struct _zval_struct {
   zvalue_value value;
   zvalue_value value;
   zend_uint refcount__gc;
   zend_uint refcount__gc;
   zend_uchar type;
   zend_uchar type;                                   typedef union _zvalue_value {
                                                      typedef union _zvalue_value {
   zend_uchar is_ref__gc;
   zend_uchar is_ref__gc;                                long lval;
                                                          long lval;
} zval;
} zval;                                                  double dval;
                                                          double dval;
                                                         struct {
                                                          struct {
                                                             char *val;
                                                              char *val;
     IS_NULL
     IS_NULL                                                 int len;
                                                              int len;
     IS_LONG
     IS_LONG                                             } str;
                                                          } str;
     IS_DOUBLE
     IS_DOUBLE                                           HashTable *ht;
                                                          HashTable *ht;
     IS_BOOL
     IS_BOOL                                             zend_object_value *obj;
                                                          zend_object_value *obj;
     IS_ARRAY
     IS_ARRAY                                         } zvalue_value;
                                                      } zvalue_value;
     IS_OBJECT
     IS_OBJECT
     IS_STRING
     IS_STRING
     IS_RESOURCE
     IS_RESOURCE
Premiers pas dans les extensions - Pierrick Charron                                   16
ZVAL
                                                      Nombre de variables qui
typedef struct _zval_struct {
typedef struct _zval_struct {                         pointent vers cette valeur
   zvalue_value value;
   zvalue_value value;
   zend_uint refcount__gc;
   zend_uint refcount__gc;
   zend_uchar type;
   zend_uchar type;
   zend_uchar is_ref__gc;
   zend_uchar is_ref__gc;                             Définit si oui ou non une valeur
                                                      est une référence
} zval;
} zval;




Premiers pas dans les extensions - Pierrick Charron                                      17
ZVAL
                                                           Nombre de variables qui
typedef struct _zval_struct {
typedef struct _zval_struct {                              pointent vers cette valeur
   zvalue_value value;
   zvalue_value value;
   zend_uint refcount__gc;
   zend_uint refcount__gc;
   zend_uchar type;
   zend_uchar type;
   zend_uchar is_ref__gc;
   zend_uchar is_ref__gc;                                  Définit si oui ou non une valeur
                                                           est une référence
} zval;
} zval;

                                            $a        $b


 $a = 10;
 $a = 10;                            value.lval = 10
                                      value.lval = 10
 $b = $a;
 $b = $a;                            refcount = 2
                                      refcount = 2
 $b = 20;
 $b = 20;                            type = IS_LONG
                                      type = IS_LONG
                                     is_ref = 0
                                      is_ref = 0


Premiers pas dans les extensions - Pierrick Charron                                           18
ZVAL
                                                           Nombre de variables qui
typedef struct _zval_struct {
typedef struct _zval_struct {                              pointent vers cette valeur
   zvalue_value value;
   zvalue_value value;
   zend_uint refcount__gc;
   zend_uint refcount__gc;
   zend_uchar type;
   zend_uchar type;
   zend_uchar is_ref__gc;
   zend_uchar is_ref__gc;                                  Définit si oui ou non une valeur
                                                           est une référence
} zval;
} zval;

                                            $a        $b


 $a = 10;
 $a = 10;                            value.lval = 10
                                      value.lval = 10              value.lval = 20
                                                                    value.lval = 20
 $b = $a;
 $b = $a;                            refcount = 2
                                      refcount = 11
                                                  2                refcount = 1
                                                                    refcount = 1
 $b = 20;
 $b = 20;                            type = IS_LONG
                                      type = IS_LONG               type = IS_LONG
                                                                    type = IS_LONG
                                     is_ref = 0
                                      is_ref = 0                   is_ref = 0
                                                                    is_ref = 0


Premiers pas dans les extensions - Pierrick Charron                                           19
ZVAL
                                                           Nombre de variables qui
typedef struct _zval_struct {
typedef struct _zval_struct {                              pointent vers cette valeur
   zvalue_value value;
   zvalue_value value;
   zend_uint refcount__gc;
   zend_uint refcount__gc;
   zend_uchar type;
   zend_uchar type;
   zend_uchar is_ref__gc;
   zend_uchar is_ref__gc;                                  Définit si oui ou non une valeur
                                                           est une référence
} zval;
} zval;

                                            $a        $b


 $a = 10;
 $a = 10;                            value.lval = 10
                                      value.lval = 10
 $b = &$a;
 $b = &$a;                           refcount = 2
                                      refcount = 2
 $b = 20;
 $b = 20;                            type = IS_LONG
                                      type = IS_LONG
                                     is_ref = 0
                                      is_ref = 1
                                               1
                                               0


Premiers pas dans les extensions - Pierrick Charron                                           20
ZVAL
                                                           Nombre de variables qui
typedef struct _zval_struct {
typedef struct _zval_struct {                              pointent vers cette valeur
   zvalue_value value;
   zvalue_value value;
   zend_uint refcount__gc;
   zend_uint refcount__gc;
   zend_uchar type;
   zend_uchar type;
   zend_uchar is_ref__gc;
   zend_uchar is_ref__gc;                                  Définit si oui ou non une valeur
                                                           est une référence
} zval;
} zval;

                                            $a        $b


 $a = 10;
 $a = 10;                            value.lval = 10
                                      value.lval = 20
                                                   20
                                                   10
 $b = &$a;
 $b = &$a;                           refcount = 2
                                      refcount = 2
 $b = 20;
 $b = 20;                            type = IS_LONG
                                      type = IS_LONG
                                     is_ref = 0
                                      is_ref = 1
                                               1
                                               0


Premiers pas dans les extensions - Pierrick Charron                                           21
ZVAL : Récuperer le type

 #define Z_TYPE(zval)
 #define Z_TYPE(zval)      (zval).type
                              (zval).type
                           (zval).type
                              (zval).type
 #define Z_TYPE(zval_p)
 #define Z_TYPE_P(zval_p) Z_TYPE(*zval_p)
                              Z_TYPE(*zval_p)
         Z_TYPE_P(zval_p) Z_TYPE(*zval_p)
         Z_TYPE(zval_p)       Z_TYPE(*zval_p)
 #define Z_TYPE(zval_pp)
 #define Z_TYPE_PP(zval_pp)Z_TYPE(**zval_pp)
                              Z_TYPE(**zval_pp)
         Z_TYPE_PP(zval_pp)Z_TYPE(**zval_pp)
         Z_TYPE(zval_pp)      Z_TYPE(**zval_pp)

 zval foo;
 zval foo;
 Z_TYPE(foo) == IS_LONG
 Z_TYPE(foo) == IS_LONG
 zval *bar;
 zval *bar;
 Z_TYPE_P(bar) == IS_BOOL
 Z_TYPE_P(bar) == IS_BOOL




Premiers pas dans les extensions - Pierrick Charron   22
ZVAL : Récuperer une valeur

 #define Z_LVAL(zval)
 #define Z_LVAL(zval)                                 (zval).value.lval
                                                      (zval).value.lval
 #define Z_BVAL(zval)
 #define Z_BVAL(zval)                                 ((zend_bool)(zval).value.lval)
                                                      ((zend_bool)(zval).value.lval)
 #define Z_DVAL(zval)
 #define Z_DVAL(zval)                                 (zval).value.dval
                                                      (zval).value.dval
 #define Z_STRVAL(zval)
 #define Z_STRVAL(zval)                               (zval).value.str.val
                                                      (zval).value.str.val
 #define Z_STRLEN(zval)
 #define Z_STRLEN(zval)                               (zval).value.str.len
                                                      (zval).value.str.len
 #define Z_ARRVAL(zval)
 #define Z_ARRVAL(zval)                               (zval).value.ht
                                                      (zval).value.ht
 #define Z_OBJVAL(zval)
 #define Z_OBJVAL(zval)                               (zval).value.obj
                                                      (zval).value.obj

 #define Z_*_P(zval_p)
 #define Z_*_P(zval_p)                                (*zval).
                                                      (*zval).
 #define Z_*_PP(zval_pp)
 #define Z_*_PP(zval_pp)                              (**zval).
                                                      (**zval).




Premiers pas dans les extensions - Pierrick Charron                                    23
ZVAL : Assigner une valeur
 ZVAL_NULL(zval);
 ZVAL_NULL(zval);                            Z_TYPE_P(zval) = IS_NULL;
                                             Z_TYPE_P(zval) = IS_NULL;
 ZVAL_LONG(zval,l);
 ZVAL_LONG(zval,l);                          Z_TYPE_P(zval) = IS_LONG;
                                             Z_TYPE_P(zval) = IS_LONG;
                                             Z_LVAL_P(zval) = l;
                                             Z_LVAL_P(zval) = l;
 ZVAL_DOUBLE(zval,d);
 ZVAL_DOUBLE(zval,d);                        Z_TYPE_P(zval) = IS_DOUBLE;
                                             Z_TYPE_P(zval) = IS_DOUBLE;
                                             Z_DVAL_P(zval) = d;
                                             Z_DVAL_P(zval) = d;

 ZVAL_STRINGL(zval,str,len,dup) Z_TYPE_P(zval) = IS_STRING;
 ZVAL_STRINGL(zval,str,len,dup) Z_TYPE_P(zval) = IS_STRING;
                                Z_STRLEN_P(zval) = len;
                                 Z_STRLEN_P(zval) = len;
                                if (dup) {{
                                 if (dup)
                                      Z_STRVAL_P(zval) = estrndup(str, len+1);
                                       Z_STRVAL_P(zval) = estrndup(str, len+1);
                                }} else {{
                                   else
                                      Z_STRVAL_P(zval) = str;
                                       Z_STRVAL_P(zval) = str;
                                }}

 ZVAL_BOOL(zval, b)
 ZVAL_BOOL(zval, b)                          Z_TYPE_P(zval) = IS_BOOLEAN;
                                             Z_TYPE_P(zval) = IS_BOOLEAN;
                                             Z_BVAL_P(zval) = b ? 1 :: 0;
                                             Z_BVAL_P(zval) = b ? 1 0;



Premiers pas dans les extensions - Pierrick Charron                               24
Conversion
 void convert_to_string(zval *);
 void convert_to_string(zval *);
 void convert_to_long(zval *);
 void convert_to_long(zval *);
 void convert_to_double(zval *);
 void convert_to_double(zval *);
 void convert_to_null(zval *);
 void convert_to_null(zval *);
 void convert_to_boolean(zval *);
 void convert_to_boolean(zval *);
 void convert_to_array(zval *);
 void convert_to_array(zval *);
 void convert_to_object(zval *);
 void convert_to_object(zval *);




Premiers pas dans les extensions - Pierrick Charron   25
Gestion de la mémoire
●   Zend dispose d'un memory manager
      ●   évite les fuites de mémoire
      ●   signature des fonctions similaires aux fonctions
          natives C




Premiers pas dans les extensions - Pierrick Charron          26
Les fonctions d'allocation
          Fonction C traditionnelle                            Fonction spécifique à PHP
void *malloc(size_t count);                            void *emalloc(size_t count);
void *calloc(size_t nmemb, size_t size);               void *ecalloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t size);                 void *erealloc(void *ptr, size_t size);
char *strdup(const char *s);                           char *estrdup(const char *s);
char *strndup(const char *s, size_t n);                char *estrndup(const char *s, size_t n);
void free(void *ptr);                                  void efree(void *ptr);




 Premiers pas dans les extensions - Pierrick Charron                                               27
Et les extensions alors ?




Premiers pas dans les extensions - Pierrick Charron     28
./ext_skel
 ●   Outil de génération de code
 ●   Génére le squelette de l'extension

$ ./ext_skel --extname=monextension
$ ./ext_skel --extname=monextension




Premiers pas dans les extensions - Pierrick Charron   29
Les fichiers de monextension
$ tree monextension
$ tree monextension
                                                      ●   Fichiers de configuration

monextension/
 monextension/
                                                          ●   Config.m4
|-- config.m4
 |-- config.m4                                            ●   Config.w32
|-- config.w32
 |-- config.w32
|-- CREDITS
 |-- CREDITS
|-- EXPERIMENTAL
 |-- EXPERIMENTAL                                     ●   Fichiers de code
|-- monextension.c
 |-- monextension.c
|-- monextension.php
 |-- monextension.php
                                                          ●   monextension.c
|-- php_monextension.h
 |-- php_monextension.h                                   ●   php_monextension.h
`-- tests
 `-- tests
    `-- 001.phpt
     `-- 001.phpt

1 directory, 8 files
1 directory, 8 files




Premiers pas dans les extensions - Pierrick Charron                                   30
Config.m4
 ●   Script de configuration sous Linux
      ●   Utilisé par ./buildconf et phpize

dnl If your extension references something external, use with:
dnl If your extension references something external, use with:

dnl PHP_ARG_WITH(monextension, for monextension support,
dnl PHP_ARG_WITH(monextension, for monextension support,
dnl Make sure that the comment is aligned:
dnl Make sure that the comment is aligned:
dnl [[ --with-monextension
dnl --with-monextension          Include monextension support])
                                  Include monextension support])

dnl Otherwise use enable:
dnl Otherwise use enable:

PHP_ARG_ENABLE(monextension, whether to enable monextension support,
dnl PHP_ARG_ENABLE(monextension, whether to enable monext support,
 dnl PHP_ARG_ENABLE(monextension, whether to enable monext support,
Make suresure that comment is aligned:
 dnl Make that the the comment is aligned:
dnl Make sure that the comment is aligned:
[dnl [[ --enable-monextension Enable monextension support])
  --enable-monextension
dnl --enable-monextension         Enable monextension support])
                                   Enable monextension support])



Premiers pas dans les extensions - Pierrick Charron                    31
Compiler monextension
●   Dynamique
$ phpize
$ phpize
$ ./configure
$ ./configure
$ make
$ make
$ make test
$ make test


●   Statique
$ ./buildconf --force
$ ./buildconf --force
$ ./configure --enable-monextension
$ ./configure --enable-monextension
$ make
$ make
$ make test
$ make test




Premiers pas dans les extensions - Pierrick Charron   32
PHPT


       Avant même de commencer à programmer,
              pensez à écrire vos tests !!!!

                     http://qa.php.net/write-test.php




Premiers pas dans les extensions - Pierrick Charron     33
php_monextension.h
●   Déclaration des données pour la liaison
    statique




Premiers pas dans les extensions - Pierrick Charron   34
monextension.c
●   #includes
●   Structures statiques
●   Fonctions PHP
●   MINFO
●   MINIT, MSHUTDOWN, RINIT, RSHUTDOWN
●   Table des fonctions
●   Définition du module


Premiers pas dans les extensions - Pierrick Charron   35
Définition du module
●   Structure permettant à PHP d'initialiser ou de
    désinitialiser le module
zend_module_entry monextension_module_entry = {{
zend_module_entry monextension_module_entry =
   STANDARD_MODULE_HEADER,
   STANDARD_MODULE_HEADER,
   "monextension",
   "monextension",
   monextension_functions,
   monextension_functions,
   PHP_MINIT(monextension),
   PHP_MINIT(monextension),
   PHP_MSHUTDOWN(monextension),
   PHP_MSHUTDOWN(monextension),
   PHP_RINIT(monextension),
   PHP_RINIT(monextension),
   PHP_RSHUTDOWN(monextension),
   PHP_RSHUTDOWN(monextension),
   PHP_MINFO(monextension),
   PHP_MINFO(monextension),
   "0.1",
   "0.1",
   STANDARD_MODULE_PROPERTIES
   STANDARD_MODULE_PROPERTIES
};
};



Premiers pas dans les extensions - Pierrick Charron   36
Liste des fonctions
const zend_function_entry monextension_functions[] = {{
const zend_function_entry monextension_functions[] =
    PHP_FE(confirm_monextension_compiled, NULL)
     PHP_FE(confirm_monextension_compiled, NULL)
    {NULL, NULL, NULL}
     {NULL, NULL, NULL}
};
};

 ●   PHP_FE(nom, signature);
 ●   PHP_FALIAS(nom, nom_original, signature);




Premiers pas dans les extensions - Pierrick Charron       37
Première fonction
monextension.c
const zend_function_entry monextension_functions[] = {{
const zend_function_entry monextension_functions[] =
    PHP_FE(monextension_helloworld, NULL)
     PHP_FE(monextension_helloworld, NULL)
    {NULL, NULL, NULL}
     {NULL, NULL, NULL}
};
};

/** … **/
 /** … **/
PHP_FUNCTION(monextension_helloworld)
 PHP_FUNCTION(monextension_helloworld)
{{
    php_printf("Hello world !!!");
    php_printf("Hello world !!!");
};
 };


php_monextension.h
PHP_FUNCTION(monextension_helloworld);
PHP_FUNCTION(monextension_helloworld);


Premiers pas dans les extensions - Pierrick Charron       38
PHP_FUNCTION
PHP_FUNCTION(monextension_helloworld)
 PHP_FUNCTION(monextension_helloworld)
{{
   php_printf("Hello world !!!");
    php_printf("Hello world !!!");
}}



void zif_monextension_helloworld(int ht, zval *return_value, zval
 void zif_monextension_helloworld(int ht, zval *return_value, zval
**return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC)
 **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC)
{{
     php_printf("Hello world !!!");
     php_printf("Hello world !!!");
}}




Premiers pas dans les extensions - Pierrick Charron                     39
Valeur de retour
●   Modifier la variable return_value (zval *)
●   Par défaut Z_TYPE_P(return_value) = IS_NULL
●   Attention ne pas retourner la valeur !

PHP_FUNCTION(monextension_helloworld)
 PHP_FUNCTION(monextension_helloworld)
{{
    ZVAL_STRING(return_value, "Hello world !!!", 1);
    ZVAL_STRING(return_value, "Hello world !!!", 1);
    return;
    return;
};
 };




Premiers pas dans les extensions - Pierrick Charron    40
RETVAL_*
                   ZVAL Macro                                         RETVAL_*
ZVAL_NULL(return_value);                               RETVAL_NULL();
ZVAL_BOOL(return_value, bval);                         RETVAL_BOOL(bval);
ZVAL_TRUE(return_value);                               RETVAL_TRUE();
ZVAL_FALSE(return_value);                              RETVAL_FALSE();
ZVAL_LONG(return_value, lval);                         RETVAL_LONG(lval);
ZVAL_DOUBLE(return_value, dval);                       RETVAL_DOUBLE(dval);
ZVAL_STRING(return_value, str, dup);                   RETVAL_STRING(str, dup);
ZVAL_STRINGL(return_value, str, len, dup);             RETVAL_STRINGL(str, len, dup);
ZVAL_RESOURCE(return_value, rval);                     RETVAL_RESOURCE(rval);

  PHP_FUNCTION(monextension_helloworld)
   PHP_FUNCTION(monextension_helloworld)
  {{
      RETVAL_STRING("Hello world !!!", 1);
       RETVAL_STRING("Hello world !!!", 1);
      /* Code executé */
       /* Code executé */
      return;
       return;
  };
   };
 Premiers pas dans les extensions - Pierrick Charron                                    41
RETURN_*
●   RETVAL_* n'interrompt pas l'exécution du code
●   RETURN_* = RETVAL_*; return;


PHP_FUNCTION(monextension_helloworld)
 PHP_FUNCTION(monextension_helloworld)
{{
    RETURN_STRING("Hello world !!!", 1);
    RETURN_STRING("Hello world !!!", 1);
    /* Code jamais executé */
     /* Code jamais executé */
};
 };




Premiers pas dans les extensions - Pierrick Charron   42
Paramètres de fonction
PHP_FUNCTION(monextension_helloworld)
 PHP_FUNCTION(monextension_helloworld)
{{
    char *name;
     char *name;
    int name_len;
     int name_len;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
          "s", &name, &name_len) == FAILURE) {{
          "s", &name, &name_len) == FAILURE)
          return;
          return;
    }}
    php_printf("Hello %s !", name);
     php_printf("Hello %s !", name);
};
 };




Premiers pas dans les extensions - Pierrick Charron         43
Paramètres de fonction
int zend_parse_parameters (int num_args TSRMLS_DC, char *type_spec, ...)
 int zend_parse_parameters (int num_args TSRMLS_DC, char *type_spec, ...)


   Spécificateur du type                     Type côté PHP           Type de donnée côté C
                b                                 Boolean                  zend_bool *
                 l                                    Entier                  long *
                d                            Virgule floatante               double *
                s                         Chaine de caractère              char **, int *
                r                               Ressource                     zval **
                a                                 Tableau                     zval **
                o                                     Objet                   zval **
                O                      Objet d'un type spécifique   zval **, zend_class_entry *
                z                                     zval                    zval **




Premiers pas dans les extensions - Pierrick Charron                                               44
Paramètres optionnels
●   Utilisation du modificateur "|"

PHP_FUNCTION(monextension_helloworld)
 PHP_FUNCTION(monextension_helloworld)
{{
    char *name = "world";
     char *name = "world";
    int name_len = sizeof("world")-1;
     int name_len = sizeof("world")-1;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
          "|s", &name, &name_len) == FAILURE) {{
          "|s", &name, &name_len) == FAILURE)
          return;
          return;
    }}
    php_printf("Hello %s !", name);
     php_printf("Hello %s !", name);
};
 };




Premiers pas dans les extensions - Pierrick Charron         45
Les tableaux (HashTable *)
●   Stockage clef valeur
●   Très rapide
      ●   Combinaison de tableau C et de listes chaînées
●   Utilisés presque partout dans le corp PHP
●   Recherche par valeur impossible




Premiers pas dans les extensions - Pierrick Charron        46
Initialiser un tableau
int array_init(zval *z); /* $array = array(); */
 int array_init(zval *z); /* $array = array(); */



PHP_FUNCTION(monextension_emptyarray)
 PHP_FUNCTION(monextension_emptyarray)
{{
    array_init(return_value);
    array_init(return_value);
};
 };




Premiers pas dans les extensions - Pierrick Charron   47
Ajout d'éléments
Tableau numérique
                   Syntaxe PHP                                          Syntaxe C
$arr[1] = null;                                        add_index_null(arr, 1);
$arr[2] = "foo";                                       add_index_string(arr, 2, "foo", 1);
$arr[3] = true;                                        add_index_bool(arr, 3, 1);
$arr[4] = 10;                                          add_index_long(arr, 4, 10);
$arr[5] = 3.1416;                                      add_index_double(arr, 5, 3.1416);
$arr[6] = $foo;                                        add_index_zval(arr, 6, foo);
$arr[] = null;                                         add_next_index_null(arr);
$arr[] = "foo";                                        add_next_index_string(arr, "foo", 1);
$arr[] = true;                                         add_next_index_bool(arr, 1);
$arr[] = 10;                                           add_next_index_long(arr, 10);
$arr[] = 3.1416;                                       add_next_index_double(arr, 3.1416);
$arr[] = $foo;                                         add_next_index_zval(arr, foo);

 Premiers pas dans les extensions - Pierrick Charron                                           48
Ajout d'éléments
Tableau associatif
        Syntaxe PHP                                            Syntaxe C
$arr["foo"] = null;                   add_assoc_null(arr, "foo");
                                      add_assoc_null_ex(arr, "foo", sizeof("foo"));
$arr["bar"] = "foo";                  add_assoc_string(arr, "bar", "foo", 1);
                                      add_assoc_string_ex(arr, "bar", sizeof("bar"), "foo", 1);
$arr["baz"] = true;                   add_assoc_bool(arr, "baz", 1);
                                      add_assoc_bool_ex(arr, "baz", sizeof("baz"), 1);
$arr["boz"] = 10;                     add_assoc_long(arr, "boz", 10);
                                      add_assoc_long_ex(arr, "boz", sizeof("boz"), 10);
$arr["biz"] = 3.1416;                 add_assoc_double(arr, "biz", 3.1416);
                                      add_assoc_double_ex(arr, "biz", sizeof("biz"), 3.1416);
$arr["buz"] = $foo;                   add_assoc_zval(arr, "buz", foo);
                                      add_assoc_zval(arr, "buz", sizeof("buz"), foo);



Premiers pas dans les extensions - Pierrick Charron                                               49
Recherche d'éléments
int zend_hash_find(const HashTable *ht,
 int zend_hash_find(const HashTable *ht,
      const char *arKey, uint nKeyLength, void **pData)
      const char *arKey, uint nKeyLength, void **pData)

int zend_hash_quick_find(const HashTable *ht,
 int zend_hash_quick_find(const HashTable *ht,
      const char *arKey, uint nKeyLength, ulong h, void **pData)
      const char *arKey, uint nKeyLength, ulong h, void **pData)
int zend_hash_index_find(const HashTable *ht, ulong h, void **pData)
 int zend_hash_index_find(const HashTable *ht, ulong h, void **pData)


zval **data;
zval **data;

if (zend_symtable_find(Z_ARRVAL(zval), "clef", sizeof("clef"), (void**)&data) ==
 if (zend_symtable_find(Z_ARRVAL(zval), "clef", sizeof("clef"), (void**)&data) ==
SUCCESS) {{
 SUCCESS)
      switch (Z_TYPE_PP(data)) {{
       switch (Z_TYPE_PP(data))
           /* ... */
            /* ... */
      }}
}}


Premiers pas dans les extensions - Pierrick Charron                                 50
Suppression d'éléments
int zend_hash_del(HashTable *ht, char *arKey, uint nKeyLen);
 int zend_hash_del(HashTable *ht, char *arKey, uint nKeyLen);
int zend_hash_quick_del(HashTable *ht, char *arKey, uint nKeyLen, ulong h);
 int zend_hash_quick_del(HashTable *ht, char *arKey, uint nKeyLen, ulong h);
int zend_hash_index_del(HashTable *ht, ulong h);
 int zend_hash_index_del(HashTable *ht, ulong h);




Premiers pas dans les extensions - Pierrick Charron                            51
Création d'une classe
zend_class_entry *counter_ce;
 zend_class_entry *counter_ce;
PHP_MINIT_FUNCTION(monextension)
 PHP_MINIT_FUNCTION(monextension)
{{
   zend_class_entry ce;
    zend_class_entry ce;
   INIT_CLASS_ENTRY(ce, "Counter", monextension_counter_methods);
    INIT_CLASS_ENTRY(ce, "Counter", monextension_counter_methods);
   counter_ce = zend_register_internal_class(&ce TSRMLS_CC);
    counter_ce = zend_register_internal_class(&ce TSRMLS_CC);
   zend_declare_property_long(counter_ce, "value", sizeof("value")-1, 0,
    zend_declare_property_long(counter_ce, "value", sizeof("value")-1, 0,
          ZEND_ACC_PUBLIC TSRMLS_CC);
          ZEND_ACC_PUBLIC TSRMLS_CC);
   return SUCCESS;
    return SUCCESS;
}}

static zend_function_entry monextension_counter_methods[] = {{
static zend_function_entry monextension_counter_methods[] =
     PHP_ME(Counter, reset, NULL, ZEND_ACC_PUBLIC)
     PHP_ME(Counter, reset, NULL, ZEND_ACC_PUBLIC)
     PHP_ME(Counter, getValue, NULL, ZEND_ACC_PUBLIC)
     PHP_ME(Counter, getValue, NULL, ZEND_ACC_PUBLIC)
     {NULL, NULL, NULL}
     {NULL, NULL, NULL}
};
};



Premiers pas dans les extensions - Pierrick Charron                         52
Les méthodes
PHP_METHOD(Counter, getValue)
 PHP_METHOD(Counter, getValue)
{{
   zval *object = getThis();
   zval *object = getThis();
   zval *details = NULL;
   zval *details = NULL;
   details = zend_read_property(counter_ce, object, "value", sizeof("value")-1, 1
   details = zend_read_property(counter_ce, object, "value", sizeof("value")-1, 1
TSRMLS_CC);
 TSRMLS_CC);
   RETURN_LONG(Z_LVAL(value));
   RETURN_LONG(Z_LVAL(value));
}}
PHP_METHOD(Counter, reset)
 PHP_METHOD(Counter, reset)
{{
    zend_update_property_long(counter_ce, getThis(), "value", sizeof("value")-1, 0
    zend_update_property_long(counter_ce, getThis(), "value", sizeof("value")-1, 0
TSRMLS_DC)
 TSRMLS_DC)
    RETURN_TRUE;
    RETURN_TRUE;
}}




Premiers pas dans les extensions - Pierrick Charron                                  53
Quelques outils bien utiles ;)




Premiers pas dans les extensions - Pierrick Charron   54
Code compatible ZTS ?




                 Compilez toujours votre PHP avec
                     --enable-maintainer-zts




Premiers pas dans les extensions - Pierrick Charron   55
Fuites de mémoire ?

                                         --with-debug
$ php -e
 $ php -e
<?php leak();
 <?php leak();
[Tue Feb 22 20:12:17 2011] Script: '-'
 [Tue Feb 22 20:12:17 2011] Script: '-'
/home/pierrick/php-src/trunk/Zend/zend_builtin_functions.c(1425) :: Freeing
 /home/pierrick/php-src/trunk/Zend/zend_builtin_functions.c(1425) Freeing
0x7FA54892B708 (3 bytes), script=-
 0x7FA54892B708 (3 bytes), script=-
=== Total 1 memory leaks detected ===
 === Total 1 memory leaks detected ===
$
$




Premiers pas dans les extensions - Pierrick Charron                           56
Fuites de mémoire ?

                                              valgrind
$ USE_ZEND_ALLOC=0 valgrind --tool=memcheck --leak-check=yes --num-
$ USE_ZEND_ALLOC=0 valgrind --tool=memcheck --leak-check=yes --num-
callers=30 --show-reachable=yes sapi/cli/php leak.php
callers=30 --show-reachable=yes sapi/cli/php leak.php
….
….
==7164== LEAK SUMMARY:
==7164== LEAK SUMMARY:
==7164== definitely lost: 0 bytes in 0 blocks
==7164== definitely lost: 0 bytes in 0 blocks
==7164== indirectly lost: 0 bytes in 0 blocks
==7164== indirectly lost: 0 bytes in 0 blocks
==7164==
==7164==   possibly lost: 0 bytes in 0 blocks
           possibly lost: 0 bytes in 0 blocks
==7164== still reachable: 1,111,059 bytes in 8,728 blocks
==7164== still reachable: 1,111,059 bytes in 8,728 blocks
==7164==
==7164==      suppressed: 0 bytes in 0 blocks
              suppressed: 0 bytes in 0 blocks
….
….



Premiers pas dans les extensions - Pierrick Charron                   57
Recherche de code ?



                                                  grep


                                     http://lxr.php.net




Premiers pas dans les extensions - Pierrick Charron       58
Premiers pas dans les extensions - Pierrick Charron   59
Premiers pas dans les extensions - Pierrick Charron   60
Segfault ?
                             GDB (gnome debugger)
$ gdb --args php -d extension=monextension.so segfault.php
 $ gdb --args php -d extension=monextension.so segfault.php
(gdb) rr
 (gdb)
Starting program: /usr/local/bin/php -d extension=monextension.so segfault.php
 Starting program: /usr/local/bin/php -d extension=monextension.so segfault.php
[Thread debugging using libthread_db enabled]
 [Thread debugging using libthread_db enabled]
[New Thread 0x7fffefd1f700 (LWP 9457)]
 [New Thread 0x7fffefd1f700 (LWP 9457)]
[Thread 0x7fffefd1f700 (LWP 9457) exited]
 [Thread 0x7fffefd1f700 (LWP 9457) exited]

Program received signal SIGSEGV, Segmentation fault.
Program received signal SIGSEGV, Segmentation fault.
__strcpy_chk () at ../sysdeps/x86_64/strcpy_chk.S:196
__strcpy_chk () at ../sysdeps/x86_64/strcpy_chk.S:196
196 ../sysdeps/x86_64/strcpy_chk.S: No such file or directory.in ../sysdeps/x86_64/strcpy_chk.S
196 ../sysdeps/x86_64/strcpy_chk.S: No such file or directory.in ../sysdeps/x86_64/strcpy_chk.S
(gdb) bt
 (gdb) bt
#0 __strcpy_chk () at ../sysdeps/x86_64/strcpy_chk.S:196
 #0 __strcpy_chk () at ../sysdeps/x86_64/strcpy_chk.S:196
#1 0x00007fffefd20b0c in strcpy (ht=<value optimized out>, return_value=<value optimized out>,
 #1 0x00007fffefd20b0c in strcpy (ht=<value optimized out>, return_value=<value optimized out>,
return_value_ptr=<value optimized out>, this_ptr=0x6, return_value_used=0, tsrm_ls=0xfa70c0) at
 return_value_ptr=<value optimized out>, this_ptr=0x6, return_value_used=0, tsrm_ls=0xfa70c0) at
/usr/include/bits/string3.h:107
 /usr/include/bits/string3.h:107
#2 zif_monextension_helloworld (ht=<value optimized out>, return_value=<value optimized out>,
 #2 zif_monextension_helloworld (ht=<value optimized out>, return_value=<value optimized out>,
return_value_ptr=<value optimized out>, this_ptr=0x6, return_value_used=0, tsrm_ls=0xfa70c0) at
 return_value_ptr=<value optimized out>, this_ptr=0x6, return_value_used=0, tsrm_ls=0xfa70c0) at
/home/pierrick/php-src/trunk/ext/monextension/monextension.c:162
 /home/pierrick/php-src/trunk/ext/monextension/monextension.c:162
#3 0x00007ffff2658b35 in xdebug_execute_internal (current_execute_data=0x7ffff7eb7050,
 #3 0x00007ffff2658b35 in xdebug_execute_internal (current_execute_data=0x7ffff7eb7050,
return_value_used=0, tsrm_ls=0xfa70c0) at /home/pierrick/installs/xdebug-2.1.0/xdebug.c:1339
 return_value_used=0, tsrm_ls=0xfa70c0) at /home/pierrick/installs/xdebug-2.1.0/xdebug.c:1339
#4 0x000000000081b777 in zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7eb7050,
 #4 0x000000000081b777 in zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7eb7050,
tsrm_ls=0xfa70c0) at /home/pierrick/php-
 tsrm_ls=0xfa70c0) at /home/pierrick/php-
 Premiers pas dans les extensions - Pierrick Charron                                               61
Besoin d'aide ?


                             Irc.EFNet.org #php.pecl

                                Mailing Lists
                     http://marc.info/?l=php-internals
                        http://marc.info/?l=pecl-dev




Premiers pas dans les extensions - Pierrick Charron      62
Envie de lecture ?


     http://www.php.net/manual/en/internals2.php

                      Advanced PHP Programming
                        par George Schlossnagle

                    Extending and Embedding PHP
                           par Sara Golemon
                         ISBN#0-6723-2704-X


Premiers pas dans les extensions - Pierrick Charron   63
Questions ?
                                        pierrick@php.net
                                        Twitter: @adoyy

                           Commentaires et présentation :
                               http://joind.in/2869




Premiers pas dans les extensions - Pierrick Charron         64

More Related Content

What's hot

Développer en natif avec C++11
Développer en natif avec C++11Développer en natif avec C++11
Développer en natif avec C++11Microsoft
 
PHPTour-2011-PHP_Extensions
PHPTour-2011-PHP_ExtensionsPHPTour-2011-PHP_Extensions
PHPTour-2011-PHP_Extensionsjulien pauli
 
Polymorphisme : un concept polymorphe !
Polymorphisme : un concept polymorphe !Polymorphisme : un concept polymorphe !
Polymorphisme : un concept polymorphe !Aurélien Regat-Barrel
 
Présentation LMAX Disruptor So@t
Présentation LMAX Disruptor So@tPrésentation LMAX Disruptor So@t
Présentation LMAX Disruptor So@tFrancois Ostyn
 
CocoaHeads Rennes #1 : Grand Central Dispatch
CocoaHeads Rennes #1 : Grand Central DispatchCocoaHeads Rennes #1 : Grand Central Dispatch
CocoaHeads Rennes #1 : Grand Central DispatchCocoaHeadsRNS
 
Démons en PHP, de inetd à ZeroMQ
Démons en PHP, de inetd à ZeroMQDémons en PHP, de inetd à ZeroMQ
Démons en PHP, de inetd à ZeroMQAmaury Bouchard
 
Codedarmor 2012 - 13/11 - Dart, un langage moderne pour le web
Codedarmor 2012 - 13/11 - Dart, un langage moderne pour le webCodedarmor 2012 - 13/11 - Dart, un langage moderne pour le web
Codedarmor 2012 - 13/11 - Dart, un langage moderne pour le webcodedarmor
 
Introduction a la compilation Aperçu de la compilation / Assembleur MIPS - C1
Introduction a la compilation  Aperçu de la compilation / Assembleur MIPS - C1Introduction a la compilation  Aperçu de la compilation / Assembleur MIPS - C1
Introduction a la compilation Aperçu de la compilation / Assembleur MIPS - C1Beligh HAMDI
 
C++11 en 12 exemples simples
C++11 en 12 exemples simplesC++11 en 12 exemples simples
C++11 en 12 exemples simplesPethrvs
 
Kevin Avignon: Roslyn - La plateforme de compilation .NET
Kevin Avignon: Roslyn - La plateforme de compilation .NETKevin Avignon: Roslyn - La plateforme de compilation .NET
Kevin Avignon: Roslyn - La plateforme de compilation .NETMSDEVMTL
 

What's hot (14)

Développer en natif avec C++11
Développer en natif avec C++11Développer en natif avec C++11
Développer en natif avec C++11
 
PHPTour-2011-PHP_Extensions
PHPTour-2011-PHP_ExtensionsPHPTour-2011-PHP_Extensions
PHPTour-2011-PHP_Extensions
 
Polymorphisme : un concept polymorphe !
Polymorphisme : un concept polymorphe !Polymorphisme : un concept polymorphe !
Polymorphisme : un concept polymorphe !
 
Présentation LMAX Disruptor So@t
Présentation LMAX Disruptor So@tPrésentation LMAX Disruptor So@t
Présentation LMAX Disruptor So@t
 
Formation python 3
Formation python 3Formation python 3
Formation python 3
 
CocoaHeads Rennes #1 : Grand Central Dispatch
CocoaHeads Rennes #1 : Grand Central DispatchCocoaHeads Rennes #1 : Grand Central Dispatch
CocoaHeads Rennes #1 : Grand Central Dispatch
 
Démons en PHP, de inetd à ZeroMQ
Démons en PHP, de inetd à ZeroMQDémons en PHP, de inetd à ZeroMQ
Démons en PHP, de inetd à ZeroMQ
 
Cours java script
Cours java scriptCours java script
Cours java script
 
Codedarmor 2012 - 13/11 - Dart, un langage moderne pour le web
Codedarmor 2012 - 13/11 - Dart, un langage moderne pour le webCodedarmor 2012 - 13/11 - Dart, un langage moderne pour le web
Codedarmor 2012 - 13/11 - Dart, un langage moderne pour le web
 
Formation python
Formation pythonFormation python
Formation python
 
Introduction a la compilation Aperçu de la compilation / Assembleur MIPS - C1
Introduction a la compilation  Aperçu de la compilation / Assembleur MIPS - C1Introduction a la compilation  Aperçu de la compilation / Assembleur MIPS - C1
Introduction a la compilation Aperçu de la compilation / Assembleur MIPS - C1
 
Cours php
Cours phpCours php
Cours php
 
C++11 en 12 exemples simples
C++11 en 12 exemples simplesC++11 en 12 exemples simples
C++11 en 12 exemples simples
 
Kevin Avignon: Roslyn - La plateforme de compilation .NET
Kevin Avignon: Roslyn - La plateforme de compilation .NETKevin Avignon: Roslyn - La plateforme de compilation .NET
Kevin Avignon: Roslyn - La plateforme de compilation .NET
 

Viewers also liked

Projektgruppe Externe Datenbanken und E-Mail-Management
Projektgruppe Externe Datenbanken und E-Mail-ManagementProjektgruppe Externe Datenbanken und E-Mail-Management
Projektgruppe Externe Datenbanken und E-Mail-ManagementJochen Götz
 
Progetto Educativo
Progetto EducativoProgetto Educativo
Progetto EducativoPop Apps
 
miguel angel chavarria portela
miguel angel chavarria portelamiguel angel chavarria portela
miguel angel chavarria portelamiguelchavarria
 
Finlandia y ecuador en educación edison salinas
Finlandia y ecuador en educación edison salinasFinlandia y ecuador en educación edison salinas
Finlandia y ecuador en educación edison salinasBannana Studios
 
Presentacion 1
Presentacion 1Presentacion 1
Presentacion 1elfrijol
 
Mouvement communal décembre 2011 - Hors-série programme stratégique transvers...
Mouvement communal décembre 2011 - Hors-série programme stratégique transvers...Mouvement communal décembre 2011 - Hors-série programme stratégique transvers...
Mouvement communal décembre 2011 - Hors-série programme stratégique transvers...Union des Villes et Communes de Wallonie
 
Fernando m.
Fernando m.Fernando m.
Fernando m.School
 
El arte.
El arte.El arte.
El arte.iara
 

Viewers also liked (20)

prueba
pruebaprueba
prueba
 
B learning pato2
B learning pato2B learning pato2
B learning pato2
 
Projektgruppe Externe Datenbanken und E-Mail-Management
Projektgruppe Externe Datenbanken und E-Mail-ManagementProjektgruppe Externe Datenbanken und E-Mail-Management
Projektgruppe Externe Datenbanken und E-Mail-Management
 
Progetto Educativo
Progetto EducativoProgetto Educativo
Progetto Educativo
 
miguel angel chavarria portela
miguel angel chavarria portelamiguel angel chavarria portela
miguel angel chavarria portela
 
5-Cm24
5-Cm245-Cm24
5-Cm24
 
Finlandia y ecuador en educación edison salinas
Finlandia y ecuador en educación edison salinasFinlandia y ecuador en educación edison salinas
Finlandia y ecuador en educación edison salinas
 
Fullet biblioteques amb DO Juneda
Fullet biblioteques amb DO JunedaFullet biblioteques amb DO Juneda
Fullet biblioteques amb DO Juneda
 
Presentacion 1
Presentacion 1Presentacion 1
Presentacion 1
 
Sivicein analisis total_2007-2011
Sivicein analisis total_2007-2011Sivicein analisis total_2007-2011
Sivicein analisis total_2007-2011
 
Washroom etiquette presentation
Washroom etiquette presentationWashroom etiquette presentation
Washroom etiquette presentation
 
Melocotón
MelocotónMelocotón
Melocotón
 
Wie finde ich freie Materialien für meine Lehre?
Wie finde ich freie Materialien für meine Lehre? Wie finde ich freie Materialien für meine Lehre?
Wie finde ich freie Materialien für meine Lehre?
 
Gestion des matières résiduelles dans la MRC de Témiscamingue
Gestion des matières résiduelles dans la MRC de TémiscamingueGestion des matières résiduelles dans la MRC de Témiscamingue
Gestion des matières résiduelles dans la MRC de Témiscamingue
 
Ciomas tps010
Ciomas tps010Ciomas tps010
Ciomas tps010
 
Unidad 4
Unidad 4Unidad 4
Unidad 4
 
Salzburg stefan i jelena
Salzburg stefan i jelenaSalzburg stefan i jelena
Salzburg stefan i jelena
 
Mouvement communal décembre 2011 - Hors-série programme stratégique transvers...
Mouvement communal décembre 2011 - Hors-série programme stratégique transvers...Mouvement communal décembre 2011 - Hors-série programme stratégique transvers...
Mouvement communal décembre 2011 - Hors-série programme stratégique transvers...
 
Fernando m.
Fernando m.Fernando m.
Fernando m.
 
El arte.
El arte.El arte.
El arte.
 

Similar to Premiers pas dans les extensions PHP

Comment développer un serveur métier en python/C++
Comment développer un serveur métier en python/C++Comment développer un serveur métier en python/C++
Comment développer un serveur métier en python/C++cppfrug
 
Cours2 initiation language arduino
Cours2   initiation language arduinoCours2   initiation language arduino
Cours2 initiation language arduinolabsud
 
Developpement web dynamique_Base de donnees.pdf
Developpement web dynamique_Base de donnees.pdfDeveloppement web dynamique_Base de donnees.pdf
Developpement web dynamique_Base de donnees.pdfrachidimstapha
 
Industrialiser le contrat dans un projet PHP
Industrialiser le contrat dans un projet PHPIndustrialiser le contrat dans un projet PHP
Industrialiser le contrat dans un projet PHPhalleck45
 
M2 INAE introduction python.pdf
M2 INAE introduction python.pdfM2 INAE introduction python.pdf
M2 INAE introduction python.pdfHajer Amdouni
 
Afup 2015 zf3 le futur de php
Afup 2015   zf3 le futur de phpAfup 2015   zf3 le futur de php
Afup 2015 zf3 le futur de phpSophie Beaupuis
 
Ops@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
Ops@viadeo : Puppet & Co... 6 mois après par Xavier KrantzOps@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
Ops@viadeo : Puppet & Co... 6 mois après par Xavier KrantzOlivier DASINI
 
Qualité logicielle
Qualité logicielleQualité logicielle
Qualité logiciellecyrilgandon
 
ESGAE_C#_2021-2024 Cours Avancé (('.pptx
ESGAE_C#_2021-2024 Cours Avancé (('.pptxESGAE_C#_2021-2024 Cours Avancé (('.pptx
ESGAE_C#_2021-2024 Cours Avancé (('.pptxLagloireSouamounou
 
02 Spécificité du C++ COURS SYS SYSSSSSS
02 Spécificité du C++  COURS SYS SYSSSSSS02 Spécificité du C++  COURS SYS SYSSSSSS
02 Spécificité du C++ COURS SYS SYSSSSSSAyoubElmrabet6
 
2013 01-08-php-maturite
2013 01-08-php-maturite2013 01-08-php-maturite
2013 01-08-php-maturiteRémi Alvado
 
Monitoring d'applications/environnements PHP : APM et Pinba
Monitoring d'applications/environnements PHP : APM et PinbaMonitoring d'applications/environnements PHP : APM et Pinba
Monitoring d'applications/environnements PHP : APM et PinbaIdaf_1er
 
Présentation LMAX / Disruptor
Présentation LMAX / DisruptorPrésentation LMAX / Disruptor
Présentation LMAX / DisruptorSOAT
 
Ateliers de base en Arduino (Carte Arduino Uno, Capteurs, Actionneurs))
Ateliers de base en Arduino (Carte Arduino Uno, Capteurs, Actionneurs))Ateliers de base en Arduino (Carte Arduino Uno, Capteurs, Actionneurs))
Ateliers de base en Arduino (Carte Arduino Uno, Capteurs, Actionneurs))Fatima Zahra Fagroud
 

Similar to Premiers pas dans les extensions PHP (20)

Comment développer un serveur métier en python/C++
Comment développer un serveur métier en python/C++Comment développer un serveur métier en python/C++
Comment développer un serveur métier en python/C++
 
Cours2 initiation language arduino
Cours2   initiation language arduinoCours2   initiation language arduino
Cours2 initiation language arduino
 
Developpement web dynamique_Base de donnees.pdf
Developpement web dynamique_Base de donnees.pdfDeveloppement web dynamique_Base de donnees.pdf
Developpement web dynamique_Base de donnees.pdf
 
Industrialiser le contrat dans un projet PHP
Industrialiser le contrat dans un projet PHPIndustrialiser le contrat dans un projet PHP
Industrialiser le contrat dans un projet PHP
 
Etes vous-pret pour php8 ?
Etes vous-pret pour php8 ?Etes vous-pret pour php8 ?
Etes vous-pret pour php8 ?
 
M2 INAE introduction python.pdf
M2 INAE introduction python.pdfM2 INAE introduction python.pdf
M2 INAE introduction python.pdf
 
IF-RMI.pdf
IF-RMI.pdfIF-RMI.pdf
IF-RMI.pdf
 
Afup 2015 zf3 le futur de php
Afup 2015   zf3 le futur de phpAfup 2015   zf3 le futur de php
Afup 2015 zf3 le futur de php
 
Ops@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
Ops@viadeo : Puppet & Co... 6 mois après par Xavier KrantzOps@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
Ops@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
 
Python après 15 ans de JAVA
Python après 15 ans de JAVAPython après 15 ans de JAVA
Python après 15 ans de JAVA
 
Qualité logicielle
Qualité logicielleQualité logicielle
Qualité logicielle
 
ESGAE_C#_2021-2024 Cours Avancé (('.pptx
ESGAE_C#_2021-2024 Cours Avancé (('.pptxESGAE_C#_2021-2024 Cours Avancé (('.pptx
ESGAE_C#_2021-2024 Cours Avancé (('.pptx
 
02 Spécificité du C++ COURS SYS SYSSSSSS
02 Spécificité du C++  COURS SYS SYSSSSSS02 Spécificité du C++  COURS SYS SYSSSSSS
02 Spécificité du C++ COURS SYS SYSSSSSS
 
2013 01-08-php-maturite
2013 01-08-php-maturite2013 01-08-php-maturite
2013 01-08-php-maturite
 
Monitoring d'applications/environnements PHP : APM et Pinba
Monitoring d'applications/environnements PHP : APM et PinbaMonitoring d'applications/environnements PHP : APM et Pinba
Monitoring d'applications/environnements PHP : APM et Pinba
 
Présentation LMAX / Disruptor
Présentation LMAX / DisruptorPrésentation LMAX / Disruptor
Présentation LMAX / Disruptor
 
Tuto VP IPSEC Site-to-site
Tuto VP IPSEC Site-to-siteTuto VP IPSEC Site-to-site
Tuto VP IPSEC Site-to-site
 
Python + ansible = ♥
Python + ansible = ♥Python + ansible = ♥
Python + ansible = ♥
 
Ateliers de base en Arduino (Carte Arduino Uno, Capteurs, Actionneurs))
Ateliers de base en Arduino (Carte Arduino Uno, Capteurs, Actionneurs))Ateliers de base en Arduino (Carte Arduino Uno, Capteurs, Actionneurs))
Ateliers de base en Arduino (Carte Arduino Uno, Capteurs, Actionneurs))
 
Symfony Best Practices
Symfony Best PracticesSymfony Best Practices
Symfony Best Practices
 

Premiers pas dans les extensions PHP

  • 1. Premiers pas dans les extensions PHP Pierrick Charron, Confoo, Mars 2011 pierrick@php.net
  • 2. Qui suis-je ? ● Consultant TI à Montréal ● Auteur de l'extension PHP Stomp ● Contributeur PHP depuis 2009 ● Core ● RFC (Request For Comment) ● Documentation (Fr & En) Premiers pas dans les extensions - Pierrick Charron 2
  • 3. Une extension ? Premiers pas dans les extensions - Pierrick Charron 3
  • 4. Pourquoi créer une extension ? ● Permettre l'utilisation d'une librairie externe ● Exemple : mysql, curl ● Améliorer les performances ● Opération impossible dans l'espace utilisateur ● Exemple : Xdebug, operator, vld ● Satisfaire sa curiosité Premiers pas dans les extensions - Pierrick Charron 4
  • 5. Avant de commencer ● Présentation basée sur PHP >= 5.3 ● Utilisation de Linux #include <stdio.h> $ echo "terminal linux" void main() { terminal linux printf("C Code"); } Premiers pas dans les extensions - Pierrick Charron 5
  • 6. Prérequis ● Familier avec PHP ● Configuration de PHP ● Installation de modules ● Connaissances en C ● Patience ● API très complet ● Beaucoup, beaucoup, beaucoup... de macros Premiers pas dans les extensions - Pierrick Charron 6
  • 7. Architecture de PHP API Serveur (SAPI) Apache FPM CLI Embed ... Zend Engine PHP Core API pour les extensions standard mysqli curl date ... Premiers pas dans les extensions - Pierrick Charron 7
  • 8. Cycle de vie d'une extension ● Différentes étapes ● MINIT : Initialisation du module ● RINIT : Initialisation de la requête ● RSHUTDOWN : Arrêt de la requête ● MSHUTDOWN : Arrêt du module ● Moment et nombre d'appels dépend du SAPI Premiers pas dans les extensions - Pierrick Charron 8
  • 9. Cycle de vie : CLI $ php monscript.php MINIT RINIT Execution du script RSHUTDOWN MSHUTDOWN Premiers pas dans les extensions - Pierrick Charron 9
  • 10. Cycle de vie : Multiprocess MINIT MINIT RINIT RINIT Execution du Script Execution du Script RSHUTDOWN RSHUTDOWN RINIT RINIT Execution du Script Execution du Script RSHUTDOWN RSHUTDOWN MSHUTDOWN MSHUTDOWN Premiers pas dans les extensions - Pierrick Charron 10
  • 11. Cycle de vie : Multithreaded MINIT RINIT RINIT Execution du Script Execution du Script RSHUTDOWN RSHUTDOWN RINIT RINIT Execution du Script Execution du Script RSHUTDOWN RSHUTDOWN MSHUTDOWN Premiers pas dans les extensions - Pierrick Charron 11
  • 12. Zend Thread Safety / TSRM ● Utilisé avec des "threaded webservers" ● Chaque thread a son propre stockage local ● Evite les accès concurrents Premiers pas dans les extensions - Pierrick Charron 12
  • 13. Les macros ZTS #define TSRMLS_D #define TSRMLS_D void ***tsrmls void ***tsrmls #define TSRMLS_DC #define TSRMLS_DC ,, TSRMLS_D TSRMLS_D #define TSRMLS_C #define TSRMLS_C tsrmls tsrmls #define TSRMLS_CC #define TSRMLS_CC ,, TSRMLS_C TSRMLS_C static void ma_fonction(int ii TSRMLS_DC); static void ma_fonction(int TSRMLS_DC); ma_function(10 TSRMLS_CC); ma_function(10 TSRMLS_CC); static void ma_fonction(int i); static void ma_fonction(int i); static void ma_fonction(int i, void ***tsrmls); static void ma_fonction(int i, void ***tsrmls); ma_function(10); ma_function(10); ma_function(10, tsrmls); ma_function(10, tsrmls); Premiers pas dans les extensions - Pierrick Charron 13
  • 14. Zend Value Premiers pas dans les extensions - Pierrick Charron 14
  • 15. ZVAL ● Zval : valeur dans espace utilisateur ● Attention valeur != variable ● Conversion de type ● Compteur de référence Premiers pas dans les extensions - Pierrick Charron 15
  • 16. ZVAL typedef struct _zval_struct { typedef struct _zval_struct { zvalue_value value; zvalue_value value; zend_uint refcount__gc; zend_uint refcount__gc; zend_uchar type; zend_uchar type; typedef union _zvalue_value { typedef union _zvalue_value { zend_uchar is_ref__gc; zend_uchar is_ref__gc; long lval; long lval; } zval; } zval; double dval; double dval; struct { struct { char *val; char *val; IS_NULL IS_NULL int len; int len; IS_LONG IS_LONG } str; } str; IS_DOUBLE IS_DOUBLE HashTable *ht; HashTable *ht; IS_BOOL IS_BOOL zend_object_value *obj; zend_object_value *obj; IS_ARRAY IS_ARRAY } zvalue_value; } zvalue_value; IS_OBJECT IS_OBJECT IS_STRING IS_STRING IS_RESOURCE IS_RESOURCE Premiers pas dans les extensions - Pierrick Charron 16
  • 17. ZVAL Nombre de variables qui typedef struct _zval_struct { typedef struct _zval_struct { pointent vers cette valeur zvalue_value value; zvalue_value value; zend_uint refcount__gc; zend_uint refcount__gc; zend_uchar type; zend_uchar type; zend_uchar is_ref__gc; zend_uchar is_ref__gc; Définit si oui ou non une valeur est une référence } zval; } zval; Premiers pas dans les extensions - Pierrick Charron 17
  • 18. ZVAL Nombre de variables qui typedef struct _zval_struct { typedef struct _zval_struct { pointent vers cette valeur zvalue_value value; zvalue_value value; zend_uint refcount__gc; zend_uint refcount__gc; zend_uchar type; zend_uchar type; zend_uchar is_ref__gc; zend_uchar is_ref__gc; Définit si oui ou non une valeur est une référence } zval; } zval; $a $b $a = 10; $a = 10; value.lval = 10 value.lval = 10 $b = $a; $b = $a; refcount = 2 refcount = 2 $b = 20; $b = 20; type = IS_LONG type = IS_LONG is_ref = 0 is_ref = 0 Premiers pas dans les extensions - Pierrick Charron 18
  • 19. ZVAL Nombre de variables qui typedef struct _zval_struct { typedef struct _zval_struct { pointent vers cette valeur zvalue_value value; zvalue_value value; zend_uint refcount__gc; zend_uint refcount__gc; zend_uchar type; zend_uchar type; zend_uchar is_ref__gc; zend_uchar is_ref__gc; Définit si oui ou non une valeur est une référence } zval; } zval; $a $b $a = 10; $a = 10; value.lval = 10 value.lval = 10 value.lval = 20 value.lval = 20 $b = $a; $b = $a; refcount = 2 refcount = 11 2 refcount = 1 refcount = 1 $b = 20; $b = 20; type = IS_LONG type = IS_LONG type = IS_LONG type = IS_LONG is_ref = 0 is_ref = 0 is_ref = 0 is_ref = 0 Premiers pas dans les extensions - Pierrick Charron 19
  • 20. ZVAL Nombre de variables qui typedef struct _zval_struct { typedef struct _zval_struct { pointent vers cette valeur zvalue_value value; zvalue_value value; zend_uint refcount__gc; zend_uint refcount__gc; zend_uchar type; zend_uchar type; zend_uchar is_ref__gc; zend_uchar is_ref__gc; Définit si oui ou non une valeur est une référence } zval; } zval; $a $b $a = 10; $a = 10; value.lval = 10 value.lval = 10 $b = &$a; $b = &$a; refcount = 2 refcount = 2 $b = 20; $b = 20; type = IS_LONG type = IS_LONG is_ref = 0 is_ref = 1 1 0 Premiers pas dans les extensions - Pierrick Charron 20
  • 21. ZVAL Nombre de variables qui typedef struct _zval_struct { typedef struct _zval_struct { pointent vers cette valeur zvalue_value value; zvalue_value value; zend_uint refcount__gc; zend_uint refcount__gc; zend_uchar type; zend_uchar type; zend_uchar is_ref__gc; zend_uchar is_ref__gc; Définit si oui ou non une valeur est une référence } zval; } zval; $a $b $a = 10; $a = 10; value.lval = 10 value.lval = 20 20 10 $b = &$a; $b = &$a; refcount = 2 refcount = 2 $b = 20; $b = 20; type = IS_LONG type = IS_LONG is_ref = 0 is_ref = 1 1 0 Premiers pas dans les extensions - Pierrick Charron 21
  • 22. ZVAL : Récuperer le type #define Z_TYPE(zval) #define Z_TYPE(zval) (zval).type (zval).type (zval).type (zval).type #define Z_TYPE(zval_p) #define Z_TYPE_P(zval_p) Z_TYPE(*zval_p) Z_TYPE(*zval_p) Z_TYPE_P(zval_p) Z_TYPE(*zval_p) Z_TYPE(zval_p) Z_TYPE(*zval_p) #define Z_TYPE(zval_pp) #define Z_TYPE_PP(zval_pp)Z_TYPE(**zval_pp) Z_TYPE(**zval_pp) Z_TYPE_PP(zval_pp)Z_TYPE(**zval_pp) Z_TYPE(zval_pp) Z_TYPE(**zval_pp) zval foo; zval foo; Z_TYPE(foo) == IS_LONG Z_TYPE(foo) == IS_LONG zval *bar; zval *bar; Z_TYPE_P(bar) == IS_BOOL Z_TYPE_P(bar) == IS_BOOL Premiers pas dans les extensions - Pierrick Charron 22
  • 23. ZVAL : Récuperer une valeur #define Z_LVAL(zval) #define Z_LVAL(zval) (zval).value.lval (zval).value.lval #define Z_BVAL(zval) #define Z_BVAL(zval) ((zend_bool)(zval).value.lval) ((zend_bool)(zval).value.lval) #define Z_DVAL(zval) #define Z_DVAL(zval) (zval).value.dval (zval).value.dval #define Z_STRVAL(zval) #define Z_STRVAL(zval) (zval).value.str.val (zval).value.str.val #define Z_STRLEN(zval) #define Z_STRLEN(zval) (zval).value.str.len (zval).value.str.len #define Z_ARRVAL(zval) #define Z_ARRVAL(zval) (zval).value.ht (zval).value.ht #define Z_OBJVAL(zval) #define Z_OBJVAL(zval) (zval).value.obj (zval).value.obj #define Z_*_P(zval_p) #define Z_*_P(zval_p) (*zval). (*zval). #define Z_*_PP(zval_pp) #define Z_*_PP(zval_pp) (**zval). (**zval). Premiers pas dans les extensions - Pierrick Charron 23
  • 24. ZVAL : Assigner une valeur ZVAL_NULL(zval); ZVAL_NULL(zval); Z_TYPE_P(zval) = IS_NULL; Z_TYPE_P(zval) = IS_NULL; ZVAL_LONG(zval,l); ZVAL_LONG(zval,l); Z_TYPE_P(zval) = IS_LONG; Z_TYPE_P(zval) = IS_LONG; Z_LVAL_P(zval) = l; Z_LVAL_P(zval) = l; ZVAL_DOUBLE(zval,d); ZVAL_DOUBLE(zval,d); Z_TYPE_P(zval) = IS_DOUBLE; Z_TYPE_P(zval) = IS_DOUBLE; Z_DVAL_P(zval) = d; Z_DVAL_P(zval) = d; ZVAL_STRINGL(zval,str,len,dup) Z_TYPE_P(zval) = IS_STRING; ZVAL_STRINGL(zval,str,len,dup) Z_TYPE_P(zval) = IS_STRING; Z_STRLEN_P(zval) = len; Z_STRLEN_P(zval) = len; if (dup) {{ if (dup) Z_STRVAL_P(zval) = estrndup(str, len+1); Z_STRVAL_P(zval) = estrndup(str, len+1); }} else {{ else Z_STRVAL_P(zval) = str; Z_STRVAL_P(zval) = str; }} ZVAL_BOOL(zval, b) ZVAL_BOOL(zval, b) Z_TYPE_P(zval) = IS_BOOLEAN; Z_TYPE_P(zval) = IS_BOOLEAN; Z_BVAL_P(zval) = b ? 1 :: 0; Z_BVAL_P(zval) = b ? 1 0; Premiers pas dans les extensions - Pierrick Charron 24
  • 25. Conversion void convert_to_string(zval *); void convert_to_string(zval *); void convert_to_long(zval *); void convert_to_long(zval *); void convert_to_double(zval *); void convert_to_double(zval *); void convert_to_null(zval *); void convert_to_null(zval *); void convert_to_boolean(zval *); void convert_to_boolean(zval *); void convert_to_array(zval *); void convert_to_array(zval *); void convert_to_object(zval *); void convert_to_object(zval *); Premiers pas dans les extensions - Pierrick Charron 25
  • 26. Gestion de la mémoire ● Zend dispose d'un memory manager ● évite les fuites de mémoire ● signature des fonctions similaires aux fonctions natives C Premiers pas dans les extensions - Pierrick Charron 26
  • 27. Les fonctions d'allocation Fonction C traditionnelle Fonction spécifique à PHP void *malloc(size_t count); void *emalloc(size_t count); void *calloc(size_t nmemb, size_t size); void *ecalloc(size_t nmemb, size_t size); void *realloc(void *ptr, size_t size); void *erealloc(void *ptr, size_t size); char *strdup(const char *s); char *estrdup(const char *s); char *strndup(const char *s, size_t n); char *estrndup(const char *s, size_t n); void free(void *ptr); void efree(void *ptr); Premiers pas dans les extensions - Pierrick Charron 27
  • 28. Et les extensions alors ? Premiers pas dans les extensions - Pierrick Charron 28
  • 29. ./ext_skel ● Outil de génération de code ● Génére le squelette de l'extension $ ./ext_skel --extname=monextension $ ./ext_skel --extname=monextension Premiers pas dans les extensions - Pierrick Charron 29
  • 30. Les fichiers de monextension $ tree monextension $ tree monextension ● Fichiers de configuration monextension/ monextension/ ● Config.m4 |-- config.m4 |-- config.m4 ● Config.w32 |-- config.w32 |-- config.w32 |-- CREDITS |-- CREDITS |-- EXPERIMENTAL |-- EXPERIMENTAL ● Fichiers de code |-- monextension.c |-- monextension.c |-- monextension.php |-- monextension.php ● monextension.c |-- php_monextension.h |-- php_monextension.h ● php_monextension.h `-- tests `-- tests `-- 001.phpt `-- 001.phpt 1 directory, 8 files 1 directory, 8 files Premiers pas dans les extensions - Pierrick Charron 30
  • 31. Config.m4 ● Script de configuration sous Linux ● Utilisé par ./buildconf et phpize dnl If your extension references something external, use with: dnl If your extension references something external, use with: dnl PHP_ARG_WITH(monextension, for monextension support, dnl PHP_ARG_WITH(monextension, for monextension support, dnl Make sure that the comment is aligned: dnl Make sure that the comment is aligned: dnl [[ --with-monextension dnl --with-monextension Include monextension support]) Include monextension support]) dnl Otherwise use enable: dnl Otherwise use enable: PHP_ARG_ENABLE(monextension, whether to enable monextension support, dnl PHP_ARG_ENABLE(monextension, whether to enable monext support, dnl PHP_ARG_ENABLE(monextension, whether to enable monext support, Make suresure that comment is aligned: dnl Make that the the comment is aligned: dnl Make sure that the comment is aligned: [dnl [[ --enable-monextension Enable monextension support]) --enable-monextension dnl --enable-monextension Enable monextension support]) Enable monextension support]) Premiers pas dans les extensions - Pierrick Charron 31
  • 32. Compiler monextension ● Dynamique $ phpize $ phpize $ ./configure $ ./configure $ make $ make $ make test $ make test ● Statique $ ./buildconf --force $ ./buildconf --force $ ./configure --enable-monextension $ ./configure --enable-monextension $ make $ make $ make test $ make test Premiers pas dans les extensions - Pierrick Charron 32
  • 33. PHPT Avant même de commencer à programmer, pensez à écrire vos tests !!!! http://qa.php.net/write-test.php Premiers pas dans les extensions - Pierrick Charron 33
  • 34. php_monextension.h ● Déclaration des données pour la liaison statique Premiers pas dans les extensions - Pierrick Charron 34
  • 35. monextension.c ● #includes ● Structures statiques ● Fonctions PHP ● MINFO ● MINIT, MSHUTDOWN, RINIT, RSHUTDOWN ● Table des fonctions ● Définition du module Premiers pas dans les extensions - Pierrick Charron 35
  • 36. Définition du module ● Structure permettant à PHP d'initialiser ou de désinitialiser le module zend_module_entry monextension_module_entry = {{ zend_module_entry monextension_module_entry = STANDARD_MODULE_HEADER, STANDARD_MODULE_HEADER, "monextension", "monextension", monextension_functions, monextension_functions, PHP_MINIT(monextension), PHP_MINIT(monextension), PHP_MSHUTDOWN(monextension), PHP_MSHUTDOWN(monextension), PHP_RINIT(monextension), PHP_RINIT(monextension), PHP_RSHUTDOWN(monextension), PHP_RSHUTDOWN(monextension), PHP_MINFO(monextension), PHP_MINFO(monextension), "0.1", "0.1", STANDARD_MODULE_PROPERTIES STANDARD_MODULE_PROPERTIES }; }; Premiers pas dans les extensions - Pierrick Charron 36
  • 37. Liste des fonctions const zend_function_entry monextension_functions[] = {{ const zend_function_entry monextension_functions[] = PHP_FE(confirm_monextension_compiled, NULL) PHP_FE(confirm_monextension_compiled, NULL) {NULL, NULL, NULL} {NULL, NULL, NULL} }; }; ● PHP_FE(nom, signature); ● PHP_FALIAS(nom, nom_original, signature); Premiers pas dans les extensions - Pierrick Charron 37
  • 38. Première fonction monextension.c const zend_function_entry monextension_functions[] = {{ const zend_function_entry monextension_functions[] = PHP_FE(monextension_helloworld, NULL) PHP_FE(monextension_helloworld, NULL) {NULL, NULL, NULL} {NULL, NULL, NULL} }; }; /** … **/ /** … **/ PHP_FUNCTION(monextension_helloworld) PHP_FUNCTION(monextension_helloworld) {{ php_printf("Hello world !!!"); php_printf("Hello world !!!"); }; }; php_monextension.h PHP_FUNCTION(monextension_helloworld); PHP_FUNCTION(monextension_helloworld); Premiers pas dans les extensions - Pierrick Charron 38
  • 39. PHP_FUNCTION PHP_FUNCTION(monextension_helloworld) PHP_FUNCTION(monextension_helloworld) {{ php_printf("Hello world !!!"); php_printf("Hello world !!!"); }} void zif_monextension_helloworld(int ht, zval *return_value, zval void zif_monextension_helloworld(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC) **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC) {{ php_printf("Hello world !!!"); php_printf("Hello world !!!"); }} Premiers pas dans les extensions - Pierrick Charron 39
  • 40. Valeur de retour ● Modifier la variable return_value (zval *) ● Par défaut Z_TYPE_P(return_value) = IS_NULL ● Attention ne pas retourner la valeur ! PHP_FUNCTION(monextension_helloworld) PHP_FUNCTION(monextension_helloworld) {{ ZVAL_STRING(return_value, "Hello world !!!", 1); ZVAL_STRING(return_value, "Hello world !!!", 1); return; return; }; }; Premiers pas dans les extensions - Pierrick Charron 40
  • 41. RETVAL_* ZVAL Macro RETVAL_* ZVAL_NULL(return_value); RETVAL_NULL(); ZVAL_BOOL(return_value, bval); RETVAL_BOOL(bval); ZVAL_TRUE(return_value); RETVAL_TRUE(); ZVAL_FALSE(return_value); RETVAL_FALSE(); ZVAL_LONG(return_value, lval); RETVAL_LONG(lval); ZVAL_DOUBLE(return_value, dval); RETVAL_DOUBLE(dval); ZVAL_STRING(return_value, str, dup); RETVAL_STRING(str, dup); ZVAL_STRINGL(return_value, str, len, dup); RETVAL_STRINGL(str, len, dup); ZVAL_RESOURCE(return_value, rval); RETVAL_RESOURCE(rval); PHP_FUNCTION(monextension_helloworld) PHP_FUNCTION(monextension_helloworld) {{ RETVAL_STRING("Hello world !!!", 1); RETVAL_STRING("Hello world !!!", 1); /* Code executé */ /* Code executé */ return; return; }; }; Premiers pas dans les extensions - Pierrick Charron 41
  • 42. RETURN_* ● RETVAL_* n'interrompt pas l'exécution du code ● RETURN_* = RETVAL_*; return; PHP_FUNCTION(monextension_helloworld) PHP_FUNCTION(monextension_helloworld) {{ RETURN_STRING("Hello world !!!", 1); RETURN_STRING("Hello world !!!", 1); /* Code jamais executé */ /* Code jamais executé */ }; }; Premiers pas dans les extensions - Pierrick Charron 42
  • 43. Paramètres de fonction PHP_FUNCTION(monextension_helloworld) PHP_FUNCTION(monextension_helloworld) {{ char *name; char *name; int name_len; int name_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {{ "s", &name, &name_len) == FAILURE) return; return; }} php_printf("Hello %s !", name); php_printf("Hello %s !", name); }; }; Premiers pas dans les extensions - Pierrick Charron 43
  • 44. Paramètres de fonction int zend_parse_parameters (int num_args TSRMLS_DC, char *type_spec, ...) int zend_parse_parameters (int num_args TSRMLS_DC, char *type_spec, ...) Spécificateur du type Type côté PHP Type de donnée côté C b Boolean zend_bool * l Entier long * d Virgule floatante double * s Chaine de caractère char **, int * r Ressource zval ** a Tableau zval ** o Objet zval ** O Objet d'un type spécifique zval **, zend_class_entry * z zval zval ** Premiers pas dans les extensions - Pierrick Charron 44
  • 45. Paramètres optionnels ● Utilisation du modificateur "|" PHP_FUNCTION(monextension_helloworld) PHP_FUNCTION(monextension_helloworld) {{ char *name = "world"; char *name = "world"; int name_len = sizeof("world")-1; int name_len = sizeof("world")-1; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) {{ "|s", &name, &name_len) == FAILURE) return; return; }} php_printf("Hello %s !", name); php_printf("Hello %s !", name); }; }; Premiers pas dans les extensions - Pierrick Charron 45
  • 46. Les tableaux (HashTable *) ● Stockage clef valeur ● Très rapide ● Combinaison de tableau C et de listes chaînées ● Utilisés presque partout dans le corp PHP ● Recherche par valeur impossible Premiers pas dans les extensions - Pierrick Charron 46
  • 47. Initialiser un tableau int array_init(zval *z); /* $array = array(); */ int array_init(zval *z); /* $array = array(); */ PHP_FUNCTION(monextension_emptyarray) PHP_FUNCTION(monextension_emptyarray) {{ array_init(return_value); array_init(return_value); }; }; Premiers pas dans les extensions - Pierrick Charron 47
  • 48. Ajout d'éléments Tableau numérique Syntaxe PHP Syntaxe C $arr[1] = null; add_index_null(arr, 1); $arr[2] = "foo"; add_index_string(arr, 2, "foo", 1); $arr[3] = true; add_index_bool(arr, 3, 1); $arr[4] = 10; add_index_long(arr, 4, 10); $arr[5] = 3.1416; add_index_double(arr, 5, 3.1416); $arr[6] = $foo; add_index_zval(arr, 6, foo); $arr[] = null; add_next_index_null(arr); $arr[] = "foo"; add_next_index_string(arr, "foo", 1); $arr[] = true; add_next_index_bool(arr, 1); $arr[] = 10; add_next_index_long(arr, 10); $arr[] = 3.1416; add_next_index_double(arr, 3.1416); $arr[] = $foo; add_next_index_zval(arr, foo); Premiers pas dans les extensions - Pierrick Charron 48
  • 49. Ajout d'éléments Tableau associatif Syntaxe PHP Syntaxe C $arr["foo"] = null; add_assoc_null(arr, "foo"); add_assoc_null_ex(arr, "foo", sizeof("foo")); $arr["bar"] = "foo"; add_assoc_string(arr, "bar", "foo", 1); add_assoc_string_ex(arr, "bar", sizeof("bar"), "foo", 1); $arr["baz"] = true; add_assoc_bool(arr, "baz", 1); add_assoc_bool_ex(arr, "baz", sizeof("baz"), 1); $arr["boz"] = 10; add_assoc_long(arr, "boz", 10); add_assoc_long_ex(arr, "boz", sizeof("boz"), 10); $arr["biz"] = 3.1416; add_assoc_double(arr, "biz", 3.1416); add_assoc_double_ex(arr, "biz", sizeof("biz"), 3.1416); $arr["buz"] = $foo; add_assoc_zval(arr, "buz", foo); add_assoc_zval(arr, "buz", sizeof("buz"), foo); Premiers pas dans les extensions - Pierrick Charron 49
  • 50. Recherche d'éléments int zend_hash_find(const HashTable *ht, int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData) const char *arKey, uint nKeyLength, void **pData) int zend_hash_quick_find(const HashTable *ht, int zend_hash_quick_find(const HashTable *ht, const char *arKey, uint nKeyLength, ulong h, void **pData) const char *arKey, uint nKeyLength, ulong h, void **pData) int zend_hash_index_find(const HashTable *ht, ulong h, void **pData) int zend_hash_index_find(const HashTable *ht, ulong h, void **pData) zval **data; zval **data; if (zend_symtable_find(Z_ARRVAL(zval), "clef", sizeof("clef"), (void**)&data) == if (zend_symtable_find(Z_ARRVAL(zval), "clef", sizeof("clef"), (void**)&data) == SUCCESS) {{ SUCCESS) switch (Z_TYPE_PP(data)) {{ switch (Z_TYPE_PP(data)) /* ... */ /* ... */ }} }} Premiers pas dans les extensions - Pierrick Charron 50
  • 51. Suppression d'éléments int zend_hash_del(HashTable *ht, char *arKey, uint nKeyLen); int zend_hash_del(HashTable *ht, char *arKey, uint nKeyLen); int zend_hash_quick_del(HashTable *ht, char *arKey, uint nKeyLen, ulong h); int zend_hash_quick_del(HashTable *ht, char *arKey, uint nKeyLen, ulong h); int zend_hash_index_del(HashTable *ht, ulong h); int zend_hash_index_del(HashTable *ht, ulong h); Premiers pas dans les extensions - Pierrick Charron 51
  • 52. Création d'une classe zend_class_entry *counter_ce; zend_class_entry *counter_ce; PHP_MINIT_FUNCTION(monextension) PHP_MINIT_FUNCTION(monextension) {{ zend_class_entry ce; zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Counter", monextension_counter_methods); INIT_CLASS_ENTRY(ce, "Counter", monextension_counter_methods); counter_ce = zend_register_internal_class(&ce TSRMLS_CC); counter_ce = zend_register_internal_class(&ce TSRMLS_CC); zend_declare_property_long(counter_ce, "value", sizeof("value")-1, 0, zend_declare_property_long(counter_ce, "value", sizeof("value")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC); ZEND_ACC_PUBLIC TSRMLS_CC); return SUCCESS; return SUCCESS; }} static zend_function_entry monextension_counter_methods[] = {{ static zend_function_entry monextension_counter_methods[] = PHP_ME(Counter, reset, NULL, ZEND_ACC_PUBLIC) PHP_ME(Counter, reset, NULL, ZEND_ACC_PUBLIC) PHP_ME(Counter, getValue, NULL, ZEND_ACC_PUBLIC) PHP_ME(Counter, getValue, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} {NULL, NULL, NULL} }; }; Premiers pas dans les extensions - Pierrick Charron 52
  • 53. Les méthodes PHP_METHOD(Counter, getValue) PHP_METHOD(Counter, getValue) {{ zval *object = getThis(); zval *object = getThis(); zval *details = NULL; zval *details = NULL; details = zend_read_property(counter_ce, object, "value", sizeof("value")-1, 1 details = zend_read_property(counter_ce, object, "value", sizeof("value")-1, 1 TSRMLS_CC); TSRMLS_CC); RETURN_LONG(Z_LVAL(value)); RETURN_LONG(Z_LVAL(value)); }} PHP_METHOD(Counter, reset) PHP_METHOD(Counter, reset) {{ zend_update_property_long(counter_ce, getThis(), "value", sizeof("value")-1, 0 zend_update_property_long(counter_ce, getThis(), "value", sizeof("value")-1, 0 TSRMLS_DC) TSRMLS_DC) RETURN_TRUE; RETURN_TRUE; }} Premiers pas dans les extensions - Pierrick Charron 53
  • 54. Quelques outils bien utiles ;) Premiers pas dans les extensions - Pierrick Charron 54
  • 55. Code compatible ZTS ? Compilez toujours votre PHP avec --enable-maintainer-zts Premiers pas dans les extensions - Pierrick Charron 55
  • 56. Fuites de mémoire ? --with-debug $ php -e $ php -e <?php leak(); <?php leak(); [Tue Feb 22 20:12:17 2011] Script: '-' [Tue Feb 22 20:12:17 2011] Script: '-' /home/pierrick/php-src/trunk/Zend/zend_builtin_functions.c(1425) :: Freeing /home/pierrick/php-src/trunk/Zend/zend_builtin_functions.c(1425) Freeing 0x7FA54892B708 (3 bytes), script=- 0x7FA54892B708 (3 bytes), script=- === Total 1 memory leaks detected === === Total 1 memory leaks detected === $ $ Premiers pas dans les extensions - Pierrick Charron 56
  • 57. Fuites de mémoire ? valgrind $ USE_ZEND_ALLOC=0 valgrind --tool=memcheck --leak-check=yes --num- $ USE_ZEND_ALLOC=0 valgrind --tool=memcheck --leak-check=yes --num- callers=30 --show-reachable=yes sapi/cli/php leak.php callers=30 --show-reachable=yes sapi/cli/php leak.php …. …. ==7164== LEAK SUMMARY: ==7164== LEAK SUMMARY: ==7164== definitely lost: 0 bytes in 0 blocks ==7164== definitely lost: 0 bytes in 0 blocks ==7164== indirectly lost: 0 bytes in 0 blocks ==7164== indirectly lost: 0 bytes in 0 blocks ==7164== ==7164== possibly lost: 0 bytes in 0 blocks possibly lost: 0 bytes in 0 blocks ==7164== still reachable: 1,111,059 bytes in 8,728 blocks ==7164== still reachable: 1,111,059 bytes in 8,728 blocks ==7164== ==7164== suppressed: 0 bytes in 0 blocks suppressed: 0 bytes in 0 blocks …. …. Premiers pas dans les extensions - Pierrick Charron 57
  • 58. Recherche de code ? grep http://lxr.php.net Premiers pas dans les extensions - Pierrick Charron 58
  • 59. Premiers pas dans les extensions - Pierrick Charron 59
  • 60. Premiers pas dans les extensions - Pierrick Charron 60
  • 61. Segfault ? GDB (gnome debugger) $ gdb --args php -d extension=monextension.so segfault.php $ gdb --args php -d extension=monextension.so segfault.php (gdb) rr (gdb) Starting program: /usr/local/bin/php -d extension=monextension.so segfault.php Starting program: /usr/local/bin/php -d extension=monextension.so segfault.php [Thread debugging using libthread_db enabled] [Thread debugging using libthread_db enabled] [New Thread 0x7fffefd1f700 (LWP 9457)] [New Thread 0x7fffefd1f700 (LWP 9457)] [Thread 0x7fffefd1f700 (LWP 9457) exited] [Thread 0x7fffefd1f700 (LWP 9457) exited] Program received signal SIGSEGV, Segmentation fault. Program received signal SIGSEGV, Segmentation fault. __strcpy_chk () at ../sysdeps/x86_64/strcpy_chk.S:196 __strcpy_chk () at ../sysdeps/x86_64/strcpy_chk.S:196 196 ../sysdeps/x86_64/strcpy_chk.S: No such file or directory.in ../sysdeps/x86_64/strcpy_chk.S 196 ../sysdeps/x86_64/strcpy_chk.S: No such file or directory.in ../sysdeps/x86_64/strcpy_chk.S (gdb) bt (gdb) bt #0 __strcpy_chk () at ../sysdeps/x86_64/strcpy_chk.S:196 #0 __strcpy_chk () at ../sysdeps/x86_64/strcpy_chk.S:196 #1 0x00007fffefd20b0c in strcpy (ht=<value optimized out>, return_value=<value optimized out>, #1 0x00007fffefd20b0c in strcpy (ht=<value optimized out>, return_value=<value optimized out>, return_value_ptr=<value optimized out>, this_ptr=0x6, return_value_used=0, tsrm_ls=0xfa70c0) at return_value_ptr=<value optimized out>, this_ptr=0x6, return_value_used=0, tsrm_ls=0xfa70c0) at /usr/include/bits/string3.h:107 /usr/include/bits/string3.h:107 #2 zif_monextension_helloworld (ht=<value optimized out>, return_value=<value optimized out>, #2 zif_monextension_helloworld (ht=<value optimized out>, return_value=<value optimized out>, return_value_ptr=<value optimized out>, this_ptr=0x6, return_value_used=0, tsrm_ls=0xfa70c0) at return_value_ptr=<value optimized out>, this_ptr=0x6, return_value_used=0, tsrm_ls=0xfa70c0) at /home/pierrick/php-src/trunk/ext/monextension/monextension.c:162 /home/pierrick/php-src/trunk/ext/monextension/monextension.c:162 #3 0x00007ffff2658b35 in xdebug_execute_internal (current_execute_data=0x7ffff7eb7050, #3 0x00007ffff2658b35 in xdebug_execute_internal (current_execute_data=0x7ffff7eb7050, return_value_used=0, tsrm_ls=0xfa70c0) at /home/pierrick/installs/xdebug-2.1.0/xdebug.c:1339 return_value_used=0, tsrm_ls=0xfa70c0) at /home/pierrick/installs/xdebug-2.1.0/xdebug.c:1339 #4 0x000000000081b777 in zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7eb7050, #4 0x000000000081b777 in zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7eb7050, tsrm_ls=0xfa70c0) at /home/pierrick/php- tsrm_ls=0xfa70c0) at /home/pierrick/php- Premiers pas dans les extensions - Pierrick Charron 61
  • 62. Besoin d'aide ? Irc.EFNet.org #php.pecl Mailing Lists http://marc.info/?l=php-internals http://marc.info/?l=pecl-dev Premiers pas dans les extensions - Pierrick Charron 62
  • 63. Envie de lecture ? http://www.php.net/manual/en/internals2.php Advanced PHP Programming par George Schlossnagle Extending and Embedding PHP par Sara Golemon ISBN#0-6723-2704-X Premiers pas dans les extensions - Pierrick Charron 63
  • 64. Questions ? pierrick@php.net Twitter: @adoyy Commentaires et présentation : http://joind.in/2869 Premiers pas dans les extensions - Pierrick Charron 64