Advertisement
Advertisement

More Related Content

Advertisement
Advertisement

Create your own PHP extension, step by step - phpDay 2012 Verona

  1. Create your own PHP extension, step by step Patrick Allaert, Derick Rethans, Rasmus Lerdorf phpDay 2012 Verona, Italy
  2. Patrick Allaert ● Founder of Libereco ● Playing with PHP/Linux for +10 years ● eZ Publish core developer ● Author of the APM PHP extension ● @patrick_allaert ● patrickallaert@php.net ● http://github.com/patrickallaert/ ● http://patrickallaert.blogspot.com/
  3. Derick Rethans ● Dutchman living in London ● PHP Engineer/Evangelist for 10gen (the MongoDB people), where I also work on the MongoDB PHP driver. ● Author of Xdebug ● Author of the mcrypt, input_filter, dbus, translit and date/time extensions
  4. Workshop overview ● Brief reminders about PHP architecture ● Configure your environment ● Grab the example extension ● Do some exercises while seeing a bit of theory
  5. PHP architecture
  6. Configuring your environment ● Debian-like: $ sudo apt-get install php5-dev
  7. Download the sample extension a) Using git: $ git clone git://github.com/patrickallaert/ PHP_Extension_Workshop.git b) Download archive at: https://github.com/patrickallaert/PHP_Extension_Wo rkshop/downloads
  8. Minimal C code (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_MYEXT ZEND_GET_MODULE(myext) #endif
  9. Compilation Prepare build environment: 1. $ phpize Configure the extension: 2. $ ./configure Compile it: 3. $ make Install it (may require root): 4. $ make install
  10. Verify installation $ php -d extension=myext.so -m You should see “myext” as part of the loaded extensions.
  11. Minimal config.m4 dnl config.m4 for myext PHP_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
  12. Exercise one: fibonacci (1/7) ● F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1
  13. Exercise one: fibonacci (2/7) function fibo($n) { switch ($n) { case 0: case 1: return $n; } return fibo($n-2) + fibo($n-1); }
  14. Exercise one: fibonacci (3/7)
  15. Exercise one: fibonacci (4/7)
  16. Exercise one: fibonacci (5/7)
  17. Exercise one: fibonacci (6/7)
  18. Exercise one: fibonacci (7/7) Compile: $ make Install: $ make install Test: $ php -d extension=myext.so -r 'echo fibonacci(35), “n”;' 9227465
  19. Exercise one: fibonacci solution The full changes required to implement the fibonacci function are available at: http://tinyurl.com/PHP-ext-fibonacci
  20. zend_parse_parameters ● Handles the conversion of PHP userspace variables into C ones. ● Generate errors in the case of missing parameters or if the type is wrong.
  21. zend_parse_parameters ● Second parameter describes Type Cod Variable type e the type of the parameter(s) Boolean b zend_bool as a string composed of Long l long characters having all a Double d double special meaning. String s char *, int (length) Path p char *, int (length) ● To mark the start of optional Class C zend_class_entry* name parameter(s), a pipe (“|”) Resource r zval* character is used. Array a zval* Object o zval* zval z zval* Zval Z zval** pointer Callback f zend_fcall_info, zend_fcall_info_cache
  22. zend_parse_parameters examples ● sleep(), usleep(), func_get_arg(): zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &long) ● bin2hex(), quotemeta(), ord(), ucfirst(): zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) ● str*pos(): zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &haystack, &haystack_len, &needle, &offset) ● var_dump(): zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) ● file_put_contents() zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pz/| lr!", &filename, &filename_len, &data, &flags, &zcontext)
  23. OpenGrok (1/2) ● Your best friend to browse PHP's source code: http://lxr.php.net/
  24. OpenGrok (2/2)
  25. 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;
  26. Types ● IS_NULL ● IS_LONG ● IS_DOUBLE ● IS_BOOL ● IS_ARRAY ● IS_OBJECT ● IS_STRING ● IS_RESOURCE ● IS_CONSTANT ● IS_CONSTANT_ARRAY ● IS_CALLABLE ● http://lxr.php.net/xref/PHP_TRUNK/Zend/zend.h#IS_NULL
  27. Access macros Z_TYPE(zval) (zval).type Z_LVAL(zval) (zval).value.lval Z_BVAL(zval) ((zend_bool)(zval).value.lval) Z_DVAL(zval) (zval).value.dval Z_STRVAL(zval) (zval).value.str.val Z_STRLEN(zval) (zval).value.str.len Z_ARRVAL(zval) (zval).value.ht Z_OBJVAL(zval) (zval).value.obj Z_OBJ_HANDLE(zval) Z_OBJVAL(zval).handle Z_OBJ_HT(zval) Z_OBJVAL(zval).handlers Z_RESVAL(zval) (zval).value.lval Z_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
  28. Exercise two: my_dump($val) (1/2) ● Create a very simple my_dump($val) function: ● my_dump(null); // null value! ● my_dump(42); // Long: 42 ● my_dump(123.456); // Double: 123.456 ● my_dump(true); // Boolean: true ● my_dump(“hello”); // String: hello
  29. Exercise two: my_dump($val) (2/2) ● Hints: ● Define a pointer to a zval: zval *val; ● Use “z” with zend_parse_parameters() ● Switch/case based on the type of val (Z_TYPE_P(uservar)) ● Use php_printf() to print, except for strings from zval, since they may contain NULL characters: PHPWRITE(const char *, size_t);
  30. Exercise two: solution PHP_FUNCTION(my_dump) { zval *val; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", val) == FAILURE) { return; } switch (Z_TYPE_P(val)) { case IS_NULL: php_printf("NULL"); break; case IS_BOOL: php_printf("Boolean: %s", Z_LVAL_P(val) ? "true" : "false"); break; case IS_LONG: php_printf("Long: %ld", Z_LVAL_P(val)); break; case IS_DOUBLE: php_printf("Double: %f", Z_DVAL_P(val)); break; case IS_STRING: php_printf("String: "); PHPWRITE(Z_STRVAL_P(val), Z_STRLEN_P(val)); break; default: php_printf("Not supported"); } }
  31. PHP life cycles ● 4 functions (2 initializations, 2 shutdowns ones) let you do stuff at specific moments of the PHP life cycles: ● PHP_MINIT_FUNCTION ● PHP_MSHUTDOWN_FUNCTION ● PHP_RINIT_FUNCTION ● PHP_RSHUTDOWN_FUNCTION
  32. PHP life cycles - CLI ● Credits: Extending and Embedding PHP by Sara Golemon (2006 June 9th)
  33. PHP life cycles – Web server (prefork) ● Credits: Extending and Embedding PHP by Sara Golemon (2006 June 9th)
  34. PHP life cycles - Web server (multi thread) ● Credits: Extending and Embedding PHP by Sara Golemon (2006 June 9th)
  35. Exercise three: MyClass (1/10) ● Steps: ● Create a class named “MyClass” ● Create a class constant ● Add some properties with various visibilities/modifiers ● Add some methods
  36. Exercise three: MyClass (2/10)
  37. Exercise three: MyClass (3/10) ● http://tinyurl.com/PHP-ext-MyClass-1
  38. Exercise three: MyClass (4/10) ● Declaring a class constant can be made from a C type: ● 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(); ● Or from a zval: ● zend_declare_class_constant();
  39. Exercise three: MyClass (5/10) ● http://tinyurl.com/PHP-ext-MyClass-2
  40. Exercise three: MyClass (6/10) ● Creating class properties can be made from a C type: ● zend_declare_property_long(); ● zend_declare_property_bool(); ● zend_declare_property_double(); ● zend_declare_property_stringl(); ● zend_declare_property_string(); ● Or from a zval: ● zend_declare_property(); ● Visibility: ● ZEND_ACC_PUBLIC, ZEND_ACC_PROTECTED, ZEND_ACC_PRIVATE ● Modifiers: ● ZEND_ACC_STATIC, ZEND_ACC_ABSTRACT, ZEND_ACC_FINAL
  41. Exercise three: MyClass (7/10) ● http://tinyurl.com/PHP-ext-MyClass-3
  42. Exercise three: MyClass (8/10)
  43. Exercise three: MyClass (9/10)
  44. Exercise three: MyClass (10/10) ● http://tinyurl.com/PHP-ext-MyClass-4
  45. Questions?
  46. Thanks ● Don't forget to rate this workshop on https://joind.in/6386
Advertisement