• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Premiers pas dans les extensions PHP, Pierrick Charron, Confoo 2011
 

Premiers pas dans les extensions PHP, Pierrick Charron, Confoo 2011

on

  • 1,471 views

 

Statistics

Views

Total Views
1,471
Views on SlideShare
1,288
Embed Views
183

Actions

Likes
0
Downloads
19
Comments
1

3 Embeds 183

http://www.berejeb.com 156
http://www.scoop.it 24
http://feeds.feedburner.com 3

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

11 of 1 previous next

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • Very good
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Premiers pas dans les extensions PHP, Pierrick Charron, Confoo 2011 Premiers pas dans les extensions PHP, Pierrick Charron, Confoo 2011 Presentation Transcript

    • Premiers pas dans les extensions PHP Pierrick Charron, Confoo, Mars 2011 pierrick@php.net
    • Qui suis-je ?● Consultant TI à Montréal● Auteur de lextension 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 lutilisation dune librairie externe ● Exemple : mysql, curl● Améliorer les performances● Opération impossible dans lespace 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 macrosPremiers 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 dune 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 dappels dépend du SAPIPremiers pas dans les extensions - Pierrick Charron 8
    • Cycle de vie : CLI$ php monscript.php MINIT RINIT Execution du script RSHUTDOWN MSHUTDOWNPremiers 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 MSHUTDOWNPremiers 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 MSHUTDOWNPremiers 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 concurrentsPremiers 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 ValuePremiers pas dans les extensions - Pierrick Charron 14
    • ZVAL● Zval : valeur dans espace utilisateur ● Attention valeur != variable● Conversion de type● Compteur de référencePremiers pas dans les extensions - Pierrick Charron 15
    • ZVALtypedef 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_RESOURCEPremiers pas dans les extensions - Pierrick Charron 16
    • ZVAL Nombre de variables quitypedef 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 quitypedef 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 = 0Premiers pas dans les extensions - Pierrick Charron 18
    • ZVAL Nombre de variables quitypedef 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 = 0Premiers pas dans les extensions - Pierrick Charron 19
    • ZVAL Nombre de variables quitypedef 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 0Premiers pas dans les extensions - Pierrick Charron 20
    • ZVAL Nombre de variables quitypedef 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 0Premiers 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_BOOLPremiers 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 dun memory manager ● évite les fuites de mémoire ● signature des fonctions similaires aux fonctions natives CPremiers pas dans les extensions - Pierrick Charron 26
    • Les fonctions dallocation Fonction C traditionnelle Fonction spécifique à PHPvoid *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 lextension$ ./ext_skel --extname=monextension$ ./ext_skel --extname=monextensionPremiers pas dans les extensions - Pierrick Charron 29
    • Les fichiers de monextension$ tree monextension$ tree monextension ● Fichiers de configurationmonextension/ 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.phpt1 directory, 8 files1 directory, 8 filesPremiers pas dans les extensions - Pierrick Charron 30
    • Config.m4 ● Script de configuration sous Linux ● Utilisé par ./buildconf et phpizednl 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-monextensiondnl --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-monextensiondnl --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 testPremiers pas dans les extensions - Pierrick Charron 32
    • PHPT Avant même de commencer à programmer, pensez à écrire vos tests !!!! http://qa.php.net/write-test.phpPremiers pas dans les extensions - Pierrick Charron 33
    • php_monextension.h● Déclaration des données pour la liaison statiquePremiers 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 modulePremiers pas dans les extensions - Pierrick Charron 35
    • Définition du module● Structure permettant à PHP dinitialiser ou de désinitialiser le modulezend_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 fonctionsconst 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 fonctionmonextension.cconst 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.hPHP_FUNCTION(monextension_helloworld);PHP_FUNCTION(monextension_helloworld);Premiers pas dans les extensions - Pierrick Charron 38
    • PHP_FUNCTIONPHP_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_* ninterrompt pas lexé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 fonctionPHP_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 fonctionint 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 dun 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 impossiblePremiers pas dans les extensions - Pierrick Charron 46
    • Initialiser un tableauint 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émentsTableau 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émentsTableau 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émentsint 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émentsint 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 dune classezend_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éthodesPHP_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, 1TSRMLS_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, 0TSRMLS_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-ztsPremiers 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) Freeing0x7FA54892B708 (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.phpcallers=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.netPremiers 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:196196 ../sysdeps/x86_64/strcpy_chk.S: No such file or directory.in ../sysdeps/x86_64/strcpy_chk.S196 ../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 daide ? Irc.EFNet.org #php.pecl Mailing Lists http://marc.info/?l=php-internals http://marc.info/?l=pecl-devPremiers 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-XPremiers pas dans les extensions - Pierrick Charron 63
    • Questions ? pierrick@php.net Twitter: @adoyy Commentaires et présentation : http://joind.in/2869Premiers pas dans les extensions - Pierrick Charron 64