Building Custom PHP                                  Extensions                         International PHP Conference 2012 ...
About me    ‣ Ioseb Dzmanashvili    ‣ Software Architect at AzRy LLC    ‣ Teacher at Caucasus School of Technology    ‣ V8...
This talk covers    ‣ Setting up development environment    ‣ Creating extension skeletons with automated tools    ‣ Build...
This talk doesn’t cover    ‣ Thread safety topics    ‣ Networking    ‣ Object oriented programming    ‣ Stream wrappers   ...
My Experience    ‣ URI Template Pecl extension      ‣ https://github.com/ioseb/uri-template    ‣ Available from Pecl chann...
What it does?  ‣ Implementation of RFC6570(URI Template)  ‣ Resource Identifier - URI)    100% compatibility with RFC3986 (...
How to use it?         // URI Template Data         $data = array(            "id"     => array("person","albums"),       ...
Why it is important?         ‣ Possibility to achieve outstanding performance         ‣ Possibility to learn PHP from insi...
Preparing development                                  environmentWednesday, December 12, 12
Installing PHP dev package         ‣ Linux(Debian)                $ sudo apt-get install php5-dev         ‣ Installing wit...
Creating extension    ‣ Creating the configuration and build files    ‣ Creating the header and basic C files, which includes...
Tools for creating extensions      ‣      Create extension manually      ‣ Use ext_skel to generate extension      ‣ Use p...
Generating extension                                with pecl-gen      ‣ Install codegen_pecl             $ pear install c...
XML descriptor (hello-world.xml)                <?xml version="1.0" ?>                <extension name="hello_world" versio...
Generated extension structure      $ tree hello_world             !""     config.m4             !""     config.w32        ...
Generated hello_world() function      PHP_FUNCTION(hello_world)      {        const char * input = NULL;        int input_...
Modifying hello_world() function  PHP_FUNCTION(hello_world)  {    const char * input = NULL;    int input_len = 0;       i...
Installing extension   ‣ Prepare build environment for PHP extension           $ phpize   ‣ Configure it           $ ./conf...
Testing hello_world() function   ‣ Create test.php file   ‣ Write test code           <?php           echo hello_world("PHP...
Cleaning extension folder   ‣ Get rid off compilation output           $ make clean   ‣ Get rid off build environment stuf...
PHP_FUNCTIONWednesday, December 12, 12
PHP_FUNCTION expansion                         PHP_FUNCTION(hello_world)                         {                        ...
Exposing internal function     function_entry hello_world_functions[] = {         PHP_FE(hello_world, hello_world_arg_info...
Parsing Function Parameters  PHP_FUNCTION(hello_world)  {    const char *input = NULL;            // variable to store par...
Available Parameter Types        Type Specifier                 C datatype                 PHP Type        b               ...
Examples of parameter formats                   // means that function expects:                   //   a) required long pa...
Zval                     _zval_struct {                         /* Variable information */                         zvalue_...
Zval - Graphical Representation                                     value                                   long lval     ...
Internal Data Types              Type Value                   Access Macros       IS_NULL                 N/A       IS_BOO...
Zval Reader Example void display_zval(zval *value) {     switch(Z_TYPE_P(value)) {         case IS_NULL:             php_p...
Returning Values                             Type Value          Access Macros       ZVAL_NULL(return_value)              ...
Returning Values                             PHP_FUNCTION(test_function)                             {                    ...
BooksWednesday, December 12, 12
Questions?Wednesday, December 12, 12
Thank You!Wednesday, December 12, 12
Upcoming SlideShare
Loading in...5
×

Building Custom PHP Extensions

4,156

Published on

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,156
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
63
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Building Custom PHP Extensions

  1. 1. Building Custom PHP Extensions International PHP Conference 2012 Tbilisi, GeorgiaWednesday, December 12, 12
  2. 2. About me ‣ Ioseb Dzmanashvili ‣ Software Architect at AzRy LLC ‣ Teacher at Caucasus School of Technology ‣ V8 JavaScript engine contributor ‣ Author of uri_template PHP extension ‣ Author of Create-Form and Edit-Form link relation types (being RFCed now).Wednesday, December 12, 12
  3. 3. This talk covers ‣ Setting up development environment ‣ Creating extension skeletons with automated tools ‣ Building and installing extensions ‣ Internals such as: ‣ Implementing and exposing C functions ‣ PHP parameter parsing ‣ VariablesWednesday, December 12, 12
  4. 4. This talk doesn’t cover ‣ Thread safety topics ‣ Networking ‣ Object oriented programming ‣ Stream wrappers ‣ MemoryWednesday, December 12, 12
  5. 5. My Experience ‣ URI Template Pecl extension ‣ https://github.com/ioseb/uri-template ‣ Available from Pecl channel ‣ http://pecl.php.net/package/uri_template ‣ Used by Guzzle HTTP client library and Drupal 8Wednesday, December 12, 12
  6. 6. What it does? ‣ Implementation of RFC6570(URI Template) ‣ Resource Identifier - URI) 100% compatibility with RFC3986 (Uniform ‣ 100% compatibility with RFC3629 (UTF-8)Wednesday, December 12, 12
  7. 7. How to use it? // URI Template Data $data = array( "id" => array("person","albums"), "token" => "12345", "fields" => array("id", "name", "picture"), ); // URI Template $template = "{/id*}{?fields,token}"; // Transformation $result = uri_template($template, $data); //Produces: /person/albums?fields=id,name,picture&token=12345Wednesday, December 12, 12
  8. 8. Why it is important? ‣ Possibility to achieve outstanding performance ‣ Possibility to learn PHP from inside outWednesday, December 12, 12
  9. 9. Preparing development environmentWednesday, December 12, 12
  10. 10. Installing PHP dev package ‣ Linux(Debian) $ sudo apt-get install php5-dev ‣ Installing with Mac Ports on Mac OS X $ sudo port install php5-devel ‣ Use XAMPP developer package as an alternative for Mac OS X (painless solution)Wednesday, December 12, 12
  11. 11. Creating extension ‣ Creating the configuration and build files ‣ Creating the header and basic C files, which includes: ‣ Creating initialization and destruction functions ‣ Including the correct headers ‣ Creating functions for use by PHP info tools ‣ Creating test filesWednesday, December 12, 12
  12. 12. Tools for creating extensions ‣ Create extension manually ‣ Use ext_skel to generate extension ‣ Use pecl-gen to generate extensionWednesday, December 12, 12
  13. 13. Generating extension with pecl-gen ‣ Install codegen_pecl $ pear install codegen_pecl ‣ Create XML descriptor for extension ‣ Generate extension skeleton $ pecl-gen hello-world.xmlWednesday, December 12, 12
  14. 14. XML descriptor (hello-world.xml) <?xml version="1.0" ?> <extension name="hello_world" version="0.1.0"> <summary>Yet another hello world PHP Extension</summary> <description> This is a sample "hello world" extension for demonstration purposes only. </description> <maintainers> <maintainer> <user>ioseb</user> <name>Ioseb Dzmanashvili</name> <email>ioseb.dzmanashvili@gmail.com</email> <role>lead</role> </maintainer> </maintainers> <license>PHP</license> <function name="hello_world" role="public"> <proto>void hello_world( string input )</proto> <summary>Prints a hello world message</summary> <code><![CDATA[ // C code goes here ]]></code> </function> </extension>Wednesday, December 12, 12
  15. 15. Generated extension structure $ tree hello_world !"" config.m4 !"" config.w32 !"" hello-world.xml !"" hello_world.c !"" manual #   !"" Makefile #   !"" file-entities.ent #   !"" functions.xml #   !"" hello-world #   #   !"" ... #   #   !"" functions #   #   #   $"" hello-world.xml #   #   !"" ini.xml #   #   $"" reference.xml #   $"" manual.xml.in !"" ... !"" php_hello_world.h $"" tests $"" hello_world.phptWednesday, December 12, 12
  16. 16. Generated hello_world() function PHP_FUNCTION(hello_world) { const char * input = NULL; int input_len = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &input, &input_len) == FAILURE) { return; } do { // C code goes here } while (0); }Wednesday, December 12, 12
  17. 17. Modifying hello_world() function PHP_FUNCTION(hello_world) { const char * input = NULL; int input_len = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &input, &input_len) == FAILURE) { return; } // our implementation php_printf("Hello world %s", input); }Wednesday, December 12, 12
  18. 18. Installing extension ‣ Prepare build environment for PHP extension $ phpize ‣ Configure it $ ./configure ‣ Compile & Install $ make && sudo make install ‣ Enable extension $ php -d extension=hello_world.so -mWednesday, December 12, 12
  19. 19. Testing hello_world() function ‣ Create test.php file ‣ Write test code <?php echo hello_world("PHP Rocks"); echo "n"; ‣ Run script $ php test.php ‣ If you see following line everything is OK $ Hello world PHP RocksWednesday, December 12, 12
  20. 20. Cleaning extension folder ‣ Get rid off compilation output $ make clean ‣ Get rid off build environment stuff $ phpize --cleanWednesday, December 12, 12
  21. 21. PHP_FUNCTIONWednesday, December 12, 12
  22. 22. PHP_FUNCTION expansion PHP_FUNCTION(hello_world) { // rest of code removed for brevity } expands tovoid zif_hello_world( zval *return_value, // 1) variable to store return value char return_value_used, // 2) if returned value was used zval *this_ptr TSRMLS_DC // 3) pointer to objects internal state)Wednesday, December 12, 12
  23. 23. Exposing internal function function_entry hello_world_functions[] = { PHP_FE(hello_world, hello_world_arg_info) { NULL, NULL, NULL } }; expands to function_entry hello_world_functions[] = { {"hello_world", zif_hello_world, hello_world_arg_info}, { NULL, NULL, NULL } };Wednesday, December 12, 12
  24. 24. Parsing Function Parameters PHP_FUNCTION(hello_world) { const char *input = NULL; // variable to store parameter value int input_len = 0; // variable to store value length if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, // 1) number of arguments "s", // 2) format string &input, // 3) address of *input variable &input_len // 4) address of input_len variable ) == FAILURE) { return; // just return if something goes wrong } // actual implementation php_printf("Hello world %s", input); }Wednesday, December 12, 12
  25. 25. Available Parameter Types Type Specifier C datatype PHP Type b zend_bool Boolean l long Integer d double Floating point s char*, int String r zval* Resource a zval* Array o zval* Object instance O zval*, zend_class_entry* Object of a specified type z zval* Non-specific zval Z zval** Dereferenced zvalWednesday, December 12, 12
  26. 26. Examples of parameter formats // means that function expects: // a) required long parameter // b) required string parameter // c) optional long parameter // d) optional zval of non-specific type zend_parse_parameters(..., "ls|lz", ...) // menas that function expects: // a) required array parameter // b) required array parameter // c) required string parameter // d) optional long parameter zend_parse_parameters(..., "aas|l", ...)Wednesday, December 12, 12
  27. 27. Zval _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; typedef struct _zval_struct zval;Wednesday, December 12, 12
  28. 28. Zval - Graphical Representation value long lval double dval str char *val int len HashTable *ht zend_object_value obj refcount__gc type is_ref__gcWednesday, December 12, 12
  29. 29. Internal Data Types Type Value Access Macros IS_NULL N/A IS_BOOL Z_BVAL_P(value) IS_LONG Z_LVAL_P(value) IS_DOUBLE Z_DVAL_P(value) IS_STRING Z_STRVAL_P(value), Z_STRLEN_P(value) IS_ARRAY Z_ARRVAL_P(value) IS_OBJECT Z_OBJVAL_P(value) IS_RESOURCE Z_RESVAL_P(value)Wednesday, December 12, 12
  30. 30. Zval Reader Example void display_zval(zval *value) { switch(Z_TYPE_P(value)) { case IS_NULL: php_printf("NULL"); break; case IS_BOOL: php_printf("BOOL %d", Z_BVAL_P(value) ? 1 : 0); break; case IS_LONG: php_printf("LONG %ld", Z_LVAL_P(value)); break; case IS_DOUBLE: php_printf("DOUBLE %f", Z_DVAL_P(value)); break; case IS_STRING: php_printf("STRING %s", Z_STRVAL_P(value)); break; case IS_RESOURCE: php_printf("RES #%ld", Z_RESVAL_P(value)); break; case IS_ARRAY: php_printf("ARRAY"); break; case IS_OBJECT: php_printf("OBJECT"); break; } }Wednesday, December 12, 12
  31. 31. Returning Values Type Value Access Macros ZVAL_NULL(return_value) RETVAL_NULL() ZVAL_BOOL(return_value) 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_RESOURCE(return_value, rval) RETVAL_RESOURCE(rval)Wednesday, December 12, 12
  32. 32. Returning Values PHP_FUNCTION(test_function) { ZVAL_NULL(return_value) }Wednesday, December 12, 12
  33. 33. BooksWednesday, December 12, 12
  34. 34. Questions?Wednesday, December 12, 12
  35. 35. Thank You!Wednesday, December 12, 12
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×