• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Atelier création d’extensions PHP
 

Atelier création d’extensions PHP

on

  • 2,361 views

Atelier création d'extensions php

Atelier création d'extensions php

Statistics

Views

Total Views
2,361
Views on SlideShare
2,341
Embed Views
20

Actions

Likes
0
Downloads
0
Comments
0

2 Embeds 20

http://www.scoop.it 16
http://a0.twimg.com 4

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
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Atelier création d’extensions PHP Atelier création d’extensions PHP Presentation Transcript

    • Atelier: Extensions PHPJulien PAULI & Patrick ALLAERT http://tinyurl.com/AtelierExtensionsPHP
    • Julien PAULI● Architecte système Linux● Expert plateforme PHP● Contributeur PHP, Apache, ZendFramework● @julienPauli● https://www.github.com/jpauli● http://julien-pauli.developpez.com
    • Patrick ALLAERT● Expert● Développeur● Formatteur● Auteur de lextension APM● Contributeur● @patrick_allaert● patrickallaert@php.net● http://github.com/patrickallaert/● http://patrickallaert.blogspot.com/
    • Informations pratiques● Atelier théorique et pratique: ○ alternance entre les phases● Machine de type Unix requise ○ Debian/Gentoo based de préférence; ○ machine virtuelle OK.● Accès Internet fortement recommandé.● Connaissances de base du langage C requises: ○ des rappels rapides seront faits.● Compilation optionelle et manuelle de PHP.
    • Rappels langage C ● Langage compilé, transformé en instructions machines par un compilateur. ● Pré-processeur et macros. ● Langage typé : ○ la taille du type dépend de la plateforme; ○ lopérateur sizeof() donne cette information: ■ char, short (int), long, (long long), ■ float, double, long double, (long long double), ■ Variantes signed et unsigned, ■ pointeur (*), ○ typedef permet de créer un type. ● Des bibliothèques C fournissent un grand nombre de types prédéfinis, exemple: glibc, uclibc, freebsd-lib,... ○ glibc fournit notamment: <inttypes.h>, <wchar.h>, <stdint.h>,...
    • Rappels langage C● Langage accédant directement à la mémoire: ○ au moyen de pointeurs; ○ attention à ne pas accéder à des zones non autorisées! ■ "Segmentation Fault".● Variables globales: ○ définies hors de toute fonction; ○ accessibles partout et à tout moment.● Variables locales: ○ définies dans une fonction; ○ accessibles uniquement dans cette fonction.
    • Rappel débogage C ● Compilez votre programme avec les symboles de débogage: $ gcc -g -c foo.c -o foo ● Pour lactiver depuis make : $ export CFLAGS="-g" && ./configure ● Activé dans PHP lors dune compilation manuelle par défaut. ● Apprenez à manipuler le débogueur gdb : $ gdb php $(gdb) ○ run (r) lance le programme ○ break (b) place un point darrêt (ligne ou symbole) ○ continue (c) avance jusquau prochain point darrêt ○ step (s) instruction suivante (pas dentrée) ○ next (n) pas suivant ○ whatis infos sur un symbole ○ print (p) contenu dun symbole ○ display traçage du contenu dun symbole
    • GDB graphiqueIl existe des GUI pour gdb : ● DDD
    • GDB graphique● Eclipse CDT (lié en Standard Create Process Launcher)
    • GDB graphique● KDevelop
    • GDB graphique● NetBeans
    • Architecture de PHP
    • Quest ce quune extension PHP ?● Morceau de code ajouté à PHP.● Langage C ○ compilation dynamique: ■ .so à indiquer dans php.ini. ○ compilation statique: ■ extension incluse dans le binaire PHP.
    • Pourquoi créer une extension?● Nouvelle fonctionnalité impossible/difficile à réaliser en PHP: ○ modification du comportement de PHP (debogueurs, caches, ...); ○ liaison avec des bibliothèques (il en existe des centaines: curl, gd, ssl, libmysql, zlib, ...); ○ création dun PHP personnalisé pour un besoin précis.● Performances: ○ en général, la raison numéro 1; ○ code C beaucoup plus rapide que code PHP.● Restreindre laccès en modification au code? ○ Code compilé, embarqué, invisible, non modifiable.
    • Installation de lenvironnement● Option 1 : aux cotés de votre installation php: ○ le code source doit être récupéré: ■ Debian-like: $ sudo apt-get install php5-dev libxml2-dev (optionnel?) $ apt-get source php5 $ sudo apt-get build-dep php5 ■ Gentoo: rien :)
    • Installation de lenvironnement ● Option 2 : installation distincte du système: ○ prérequis: ■ autoconf: 2.13 (2.59+ for PHP 5.4+) ■ automake: 1.4+ ■ libtool: 1.4.x+ (except 1.4.2) ■ bison: 1.28, 1.35, 1.75, 2.0 or higher ■ flex (PHP 5.2 and earlier): 2.5.4 (not higher) ■ re2c: 0.13.4 ○ installation/compilation:$ mkdir sources && cd sources$ wget http://fr2.php.net/get/php-5.3.8.tar.gz/from/fr.php.net/mirror$ ./configure --prefix=/my/install/path --enable-debug --disable-all$ make && make install$ /my/install/path/bin/php -v
    • Installation de lenvironnement ● Les binaires crées intéressants: ○ phpize: ■ permet de configurer les sources dune extension; ○ php-config: ■ permet de configurer une extension.
    • Créer une nouvelle extension (ext_skel)● Il est possible dutiliser le script phpsrc/ext/ext_skel.sh pour générer un squelette dextension (un peu plus fourni que via Pyrus): ext/ext_skel --ext-name=myext● Basé sur: http://svn.php.net/viewvc/php/php-src/trunk/ext/skeleton/
    • Créer une nouvelle extension (Pyrus)1. Télécharger pyrus.phar sur http://pear2.php.net/ $ wget http://pear2.php.net/pyrus.phar2. Générer un squelette dextension avec Pyrus: $ php chemin/vers/pyrus.phar generate-ext myext
    • Créer une nouvelle extension (Pyrus)Étapes à exécuter pour utiliser lextension myext:$ cd myext$ edit README, CREDITS, RELEASE-0.1.0$ edit config.m4 and config.w32$ phpize$ ./configure$ make$ php -n -dextension_dir=`pwd`/modules -dextension=myext.so myext.php$ edit myext.c to correct errors$ makeEn cas derreur: "CDPATH: command not found" il est nécessaire de faire:$ aclocal && autoreconf -fviavant ./configure.
    • config.m4 minimaldnl config.m4 for myextPHP_ARG_ENABLE(myext, whether to enable myext support,[ --enable-myext Enable myext support])if test "$PHP_MYEXT" != "no"; then PHP_NEW_EXTENSION(myext, myext.c, $ext_shared)fi
    • Code minimal (myext.c)#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "php.h"#include "php_ini.h"#include "ext/standard/info.h"#include "php_myext.h"zend_module_entry myext_module_entry = { STANDARD_MODULE_HEADER, "myext", NULL, /* Function entries */ NULL, /* Module init */ NULL, /* Module shutdown */ NULL, /* Request init */ NULL, /* Request shutdown */ NULL, /* Module information */ "0.1", /* Replace with version number for your extension */ STANDARD_MODULE_PROPERTIES};#ifdef COMPILE_DL_MYEXTZEND_GET_MODULE(myext)#endif
    • Compilation et vérification delextension$ phpize$ ./configure$ make$ make install$ php -n -dextension_dir=`pwd`/modules -dextension=myext.so -m[PHP Modules]...mbstringmcryptmyextmysqlmysqli...Astuce : make accepte les paramètres : ● -j <nombre maximum de jobs gcc simultanés> ● -l <load maximum à ne pas dépasser>
    • Créer une nouvelle extension (fork!)Un autre moyen de démarrer une extension est de partir duneextension minimale existante.Dans le cadre de cet atelier, vous êtes encouragé à utiliser ledépôt: https://github.com/patrickallaert/PHP_Extension_WorkshopVous pouvez le récupérer au moyen de la commande:$ git clone git://github.com/patrickallaert/PHP_Extension_Workshop.gitAfin de pouvoir pousser des changements et créer votre propreextension sur base de celle-ci, vous pouvez également 1. forker ce dépôt; 2. le cloner localement : $ git clone git@github.com:<votre-login>/PHP_Extension_Workshop.git
    • Une première fonction (fibonacci) (1) ● Définir la fonction dans le tableau de définition des fonctions:zend_function_entry myext_functions[] ={ ZEND_FE(fibonacci,arginfo_fibonacci) {NULL,NULL,NULL} /* Marks the end of function entries */}; ● Référencement de la liste de fonction dans la structure définissant lextension:zend_module_entry myext_module_entry = { STANDARD_MODULE_HEADER, "myext", myext_functions, /* Function entries */ NULL, /* Module init */ NULL, /* Module shutdown */ NULL, /* Request init */ NULL, /* Request shutdown */ NULL, /* Module information */ "0.1", /* Replace with version number for your extension */ STANDARD_MODULE_PROPERTIES};
    • Une première fonction (fibonacci) (2) ● Déclaration du prototype dans le fichier de hearders (.h)PHP_FUNCTION(fibonacci); ● Implémentation de la fonction PHPPHP_FUNCTION(fibonacci){ long n; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &n) == FAILURE) { RETURN_FALSE; } RETURN_LONG(fibonacci_internal(n));}
    • Une première fonction (fibonacci) (3) ● Implémentation de la sous-fonction C utilisée:fibonacci_internal(long n){ switch(n) { case 0: case 1: return n; } return fibonacci_internal(n-2) + fibonacci_internal(n-1);}https://github.com/patrickallaert/PHP_Extension_Workshop/compare/master...fibonacci
    • Exercice: La fonction factoriellePour rappel:factorielle(0) = 1factorielle(1) = 1factorielle(n) = 1 * 2 * ... * nfactorielle(n) = n * factorielle(n-1)
    • zend_parse_parametersMéthode permettant de récolter dans des variables les arguments donnés àune fonction.Lélément clé est le deuxième paramètre de cette fonction qui est une stringdécrivant les arguments de la fonction PHP. Les arguments optionnels setrouvent après le caractère "|".Chaque argument est décrit par une lettre: Type Code Variable type Boolean b zend_bool Long l long Double d double String s char * + int (length) Path p char * + int (length) Class name C zend_class_entry* Resource r zval* Array a zval* Object o zval* zval z zval* zval Z zval** Callback f zend_fcall_info + zend_fcall_info_cache
    • Les cycles de vie4 fonctions (2 dinitialisation et 2 de terminaison) permettentdeffectuer des traitements à des moments clés du cycle de viedun serveur web, dun script ou dune requête. ● PHP_MINIT_FUNCTION ● PHP_MSHUTDOWN_FUNCTION ● PHP_RINIT_FUNCTION ● PHP_RSHUTDOWN_FUNCTION
    • Les cycles de vie - CLI Crédits: Extending and Embedding PHP par Sara Golemon (9 juin 2006)
    • Les cycles de vie - Serveur Web multi-processus Crédits: Extending and Embedding PHP par Sara Golemon (9 juin 2006)
    • Les cycles de vie - Serveur Web multi-threads Crédits: Extending and Embedding PHP par Sara Golemon (9 juin 2006)
    • Définition dune constanteMacros denregistrement des constantesREGISTER_LONG_CONSTANT(name, lval, flags)REGISTER_DOUBLE_CONSTANT(name, dval, flags)REGISTER_STRING_CONSTANT(name, str, flags)REGISTER_STRINGL_CONSTANT(name, str, len, flags)REGISTER_NS_LONG_CONSTANT(ns, name, lval, flags)REGISTER_NS_DOUBLE_CONSTANT(ns, name, dval, flags)REGISTER_NS_STRING_CONSTANT(ns, name, str, flags)REGISTER_NS_STRINGL_CONSTANT(ns, name, str, len, flags)Définition lors du chargement de lextension:PHP_MINIT_FUNCTION(myext){ REGISTER_DOUBLE_CONSTANT("PI", 3.14159265358979, CONST_CS | CONST_PERSISTENT); return SUCCESS;}https://github.com/patrickallaert/PHP_Extension_Workshop/compare/master...constant
    • Lecture de paramètres INIDéfinition des paramètres:PHP_INI_BEGIN() PHP_INI_ENTRY("myext.database", NULL, PHP_INI_SYSTEM, NULL) PHP_INI_ENTRY("myext.port", NULL, PHP_INI_SYSTEM, OnUpdateLongGEZero) PHP_INI_ENTRY("myext.username", "root", PHP_INI_ALL, NULL) PHP_INI_ENTRY("myext.password", "", PHP_INI_ALL, NULL)PHP_INI_END()Utilisation de ces paramètres:INI_INT(name)INI_FLT(name)INI_STR(name)INI_BOOL(name)Exemple:INI_STR("myext.database")INI_INT("myext.port")
    • Exercice: Constantes et configurationDéfinir quelques constantes dont la valeur est lue enconfigurationhttps://github.com/patrickallaert/PHP_Extension_Workshop/compare/master...ini_constant
    • zval (=== _zval_struct)struct _zval_struct { /* Variable information */ zvalue_value value; /* value */ zend_uint refcount__gc; zend_uchar type; /* active type */ zend_uchar is_ref__gc;};typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ struct { char *val; int len; } str; HashTable *ht; /* hash table value */ zend_object_value obj;} zvalue_value;
    • TypesIS_NULLIS_LONGIS_DOUBLEIS_BOOLIS_ARRAYIS_OBJECTIS_STRINGIS_RESOURCEIS_CONSTANTIS_CONSTANT_ARRAYIS_CALLABLEhttp://lxr.php.net/xref/PHP_TRUNK/Zend/zend.h#IS_NULL
    • Macros daccèsZ_TYPE(zval) (zval).typeZ_LVAL(zval) (zval).value.lvalZ_BVAL(zval) ((zend_bool)(zval).value.lval)Z_DVAL(zval) (zval).value.dvalZ_STRVAL(zval) (zval).value.str.valZ_STRLEN(zval) (zval).value.str.lenZ_ARRVAL(zval) (zval).value.htZ_OBJVAL(zval) (zval).value.objZ_OBJ_HANDLE(zval) Z_OBJVAL(zval).handleZ_OBJ_HT(zval) Z_OBJVAL(zval).handlersZ_RESVAL(zval) (zval).value.lvalZ_TYPE_P(zval_p) Z_TYPE(*zval_p)Z_LVAL_P(zval_p) Z_LVAL(*zval_p)Z_BVAL_P(zval_p) Z_BVAL(*zval_p)Z_DVAL_P(zval_p) Z_DVAL(*zval_p)Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p)Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p)Z_ARRVAL_P(zval_p) Z_ARRVAL(*zval_p)Z_RESVAL_P(zval_p) Z_RESVAL(*zval_p)Z_OBJVAL_P(zval_p) Z_OBJVAL(*zval_p)Z_OBJ_HANDLE_P(zval_p) Z_OBJ_HANDLE(*zval_p)Z_OBJ_HT_P(zval_p) Z_OBJ_HT(*zval_p)http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_operators.h#Z_LVAL
    • Gestion des symboles PHP et zvals ● refcount indique le nombre de symboles utilisant la zval ● Lorsque le refcount atteint zéro, la zval est détruite de la mémoire ● is_ref indique quun symbole a été affecté par référence sur la zval ● Si vous utilisez une zval en interne, vous devez gérer correctement is_ref et refcount
    • Manipulation de refcount/is_refzval_copy_ctor(zval *zval_ptr );zval_dtor(zval *zval_ptr);MAKE_COPY_ZVAL(zval **ppzv, zval *pzv);SEPARATE_ZVAL(zval **ppzv);zval_ptr_dtor(zval **ppzv)Z_REFCOUNT(z)Z_SET_REFCOUNT(z, rc)Z_ADDREF(z)Z_DELREF(z)Z_ISREF(z)Z_SET_ISREF(z)Z_UNSET_ISREF(z)Z_SET_ISREF_TO(z, isref)http://lxr.php.net/xref/PHP_TRUNK/Zend/zend.h
    • Manipuler des zval● On ne manipule jamais les champs dune zval de manière directe : ○ les macros existent à cette fin et sont recommandées; ○ une modification de la structure interne dune zval reste ainsi possible, il suffit de modifier les macros en conséquence (ex: champs isref/refcount modifiés en PHP 5.3).● Attention aux chaines de caractères binary safe (pouvant être composées du caractère nul, la structure encapsule ainsi leur taille).
    • Exercice: Manipulation de zvalÉcrire une fonction faisant certaines opérations sur base dutype du paramètre fourni. (var_dump simplifié pour une valeurscalaire?)https://github.com/patrickallaert/PHP_Extension_Workshop/compare/master...zval
    • Manipuler phpinfo() ● Référencement de la fonction PHP_MINFO dans la structure définissant lextension:zend_module_entry myext_module_entry = { STANDARD_MODULE_HEADER, "myext", NULL, /* Function entries */ NULL, /* Module init */ NULL, /* Module shutdown */ NULL, /* Request init */ NULL, /* Request shutdown */ PHP_MINFO(myext), /* Module information */ "0.1", /* Replace with version number for your extension */ STANDARD_MODULE_PROPERTIES}; ● Coder la fonction:PHP_MINFO_FUNCTION(myext){ php_info_print_table_start(); php_info_print_table_header(2, "myext support", "enabled"); php_info_print_table_end();}https://github.com/patrickallaert/PHP_Extension_Workshop/compare/master...info
    • Exercice: phpinfo()Écrire des informations supplémentaires dans phpinfo(): crédits+ directives de configuration (DISPLAY_INI_ENTRIES()).
    • Créer une classe ● Définition dun pointeur global pour lentrée de cette classe:zend_class_entry *ce_MyClass; ● Dans le MINIT, création de la classe:PHP_MINIT_FUNCTION(myext){ zend_class_entry ce; INIT_CLASS_ENTRY(ce, "MyClass", NULL); // Pas de handler de création de lobjet (!= constructeur) ce.create_object = NULL; ce_MyClass = zend_register_internal_class(&ce TSRMLS_CC);}https://github.com/patrickallaert/PHP_Extension_Workshop/compare/master...class_minimal
    • Exercice: créer une classe nativeCréer une classe "Logger" native.
    • Ajouter une constante de classe ● À partir dune zval: zend_declare_class_constant(); ● À partir dun type C:zend_declare_class_constant_null();zend_declare_class_constant_long();zend_declare_class_constant_bool();zend_declare_class_constant_double();zend_declare_class_constant_stringl();zend_declare_class_constant_string();http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_API.h ● Exemple:PHP_MINIT_FUNCTION(myext){ zend_class_entry ce; INIT_CLASS_ENTRY(ce, "MyClass", NULL); // Pas de handler de création de lobjet (!= constructeur) ce.create_object = NULL; ce_MyClass = zend_register_internal_class(&ce TSRMLS_CC); zend_declare_class_constant_long(ce_MyClass, ZEND_STRL("ULTIMATE_ANSWER"), 42 TSRMLS_CC);}https://github.com/patrickallaert/PHP_Extension_Workshop/compare/class_minimal...class_constant
    • Exercice: ajouter une constante declasseAjouter les constantes numériques "INFO", "DEBUG" et"ERROR" à la classe Logger.
    • Ajouter des propriétés à une classe ● Non initialisée:zend_declare_property_null(); ● À partir dune zval:zend_declare_property(); ● À partir dun type C:zend_declare_property_bool();zend_declare_property_long();zend_declare_property_double();zend_declare_property_string();zend_declare_property_stringl();http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_API.h ● Visibilité:ZEND_ACC_PUBLIC, ZEND_ACC_PROTECTED, ZEND_ACC_PRIVATE ● Modificateurs:ZEND_ACC_STATIC, ZEND_ACC_ABSTRACT, ZEND_ACC_FINALhttp://lxr.php.net/xref/PHP_TRUNK/Zend/zend_compile.h#ZEND_ACC_STATIC
    • Ajouter des propriétés à une classeExemple:PHP_MINIT_FUNCTION(myext){ zend_class_entry ce; INIT_CLASS_ENTRY(ce, "MyClass", NULL); // Pas de handler de création de lobjet (!= constructeur) ce.create_object = NULL; ce_MyClass = zend_register_internal_class(&ce TSRMLS_CC); zend_declare_property_null( ce_MyClass, ZEND_STRL("aPublicProperty"), ZEND_ACC_PUBLIC TSRMLS_CC ); zend_declare_property_string( ce_MyClass, ZEND_STRL("aProtectedProperty"), "I am protected", ZEND_ACC_PROTECTED TSRMLS_CC); zend_declare_property_string( ce_MyClass, ZEND_STRL("aPrivateProperty"), "I am private", ZEND_ACC_PROTECTED TSRMLS_CC ); zend_declare_property_long( ce_MyClass, ZEND_STRL("aStaticPublicProperty"), 0, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC TSRMLS_CC );}https://github.com/patrickallaert/PHP_Extension_Workshop/compare/class_minimal...class_properties
    • Ajouter des méthodes à une classe ● Définir pour chaque méthode un tableau de paramètresZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) ZEND_ARG_INFO(pass_by_ref, name)ZEND_END_ARG_INFO ● ExempleZEND_BEGIN_ARG_INFO_EX(arginfo_myclass___construct, 0, 0, 0) ZEND_ARG_INFO(0, value)ZEND_END_ARG_INFO()ZEND_BEGIN_ARG_INFO_EX(arginfo_myclass_foo, 0, 0, 2) ZEND_ARG_INFO(0, arg1) ZEND_ARG_INFO(1, arg2)ZEND_END_ARG_INFO() ● Définir un tableau avec les méthodesstatic zend_function_entry myclass_class_functions[] = { PHP_ME( MyClass, __construct, arginfo_myclass___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR ) PHP_ME( MyClass, foo, arginfo_myclass_foo, ZEND_ACC_PUBLIC )};
    • Ajouter des méthodes à une classe ● Référencer le tableau de méthodes dans linitialisation de la classe:PHP_MINIT_FUNCTION(myext){ zend_class_entry ce; INIT_CLASS_ENTRY(ce, "MyClass", myclass_class_functions); // Pas de handler de création de lobjet (!= constructeur) ce.create_object = NULL; ce_MyClass = zend_register_internal_class(&ce TSRMLS_CC);}
    • Ajouter des méthodes à une classe ● Implémentation de la méthode:PHP_METHOD(MyClass, foo){ long number; zval *string; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &number, &string) == FAILURE) { return; } php_printf( "Number: %ld, String: %sn", number, Z_STRVAL_P(string));}https://github.com/patrickallaert/PHP_Extension_Workshop/compare/class_minimal...class_method
    • Exercice: Implémentation dun LoggerImplémentation complète dune classe Logger: ● niveaux de log (voir constantes définies plus tôt); ● écriture dans un fichier; ● fichier de log configurable depuis le php.inihttps://github.com/patrickallaert/PHP_Extension_Workshop/compare/class_properties...class_logger
    • Quelques extensions● APM: implémente une méthode derror_callback interne permettant de stocker les erreurs survenant sur un système dans différents backends et avec plus dinformations.● APC: extension de cache et doptimisation des performances● XDebug: extension permettant le déboggage et le profilage dune application PHP.● Xhprof: extension de profilage hiérarchique prévu pour les systèmes en production.● Pinba: permet le stockage de données de profilage dans MySQL avec zéro impact sur les performances.
    • Quelques extensions● Yaml: permet dexploiter la bibliothèque C LibYaml permettant de lire les fichiers de données YAML.● amfext: permet lencodage/décodage de données AMF.● Memcache(d): permet laccès à un serveur Memcached.● Haru: permet dexploiter la bibliothèque C libHaru qui permet la création de PDF complexes.● mongo: permet laccès à une base de données MongoDB.● CUBRID: permet laccès à une base de données CUBRID.● solr: permet laccès à un serveur Apache Solr.● quickhash: fourni de nouvelles structures de sets et hashs à faible utilisation de mémoire.
    • Questions?
    • Références● http://julien-pauli.developpez.com/tutoriels/php/internals/bases-creer-extension/● http://julien-pauli.developpez.com/tutoriels/php/internals/presentation/● http://julien-pauli.developpez.com/tutoriels/php/compilation/● http://patrickallaert.blogspot.com/search/label/PHP● http://devzone.zend.com/node/view/id/1021● http://www.php.net/manual/en/internals2.php● http://lxr.php.net/