Transcript
Page 1: Create your own PHP extension, step by step - phpDay 2012 Verona

Create your own PHP extension, step by stepPatrick Allaert, Derick Rethans, Rasmus Lerdorf

phpDay 2012 Verona, Italy

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

Patrick Allaert● Founder of Libereco● Playing with PHP/Linux for +10 years● eZ Publish core developer● Author of the APM PHP extension● @patrick_allaert● [email protected]● http://github.com/patrickallaert/● http://patrickallaert.blogspot.com/

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

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

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

Workshop overview

● Brief reminders about PHP architecture● Configure your environment● Grab the example extension● Do some exercises while seeing a bit of theory

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

PHP architecture

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

Configuring your environment

● Debian-like:

$ sudo apt-get install php5-dev

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

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_Workshop/downloads

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

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_MYEXTZEND_GET_MODULE(myext)#endif

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

Compilation

Prepare build environment:

1. $ phpize

Configure the extension:

2. $ ./configure

Compile it:

3. $ make

Install it (may require root):

4. $ make install

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

Verify installation

$ php -d extension=myext.so -m

You should see “myext” as part of the loaded extensions.

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

Minimal config.m4dnl 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

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

Exercise one: fibonacci (1/7)

● F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1

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

Exercise one: fibonacci (2/7)

function fibo($n) { switch ($n) { case 0: case 1: return $n; }

return fibo($n-2) + fibo($n-1);}

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

Exercise one: fibonacci (3/7)

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

Exercise one: fibonacci (4/7)

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

Exercise one: fibonacci (5/7)

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

Exercise one: fibonacci (6/7)

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

Exercise one: fibonacci (7/7)

Compile:

$ make

Install:

$ make install

Test:

$ php -d extension=myext.so \ -r 'echo fibonacci(35), “\n”;'

9227465

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

Exercise one: fibonacci solution

The full changes required to implement the fibonacci function are available at:

http://tinyurl.com/PHP-ext-fibonacci

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

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.

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

zend_parse_parameters● Second parameter describes

the type of the parameter(s) as a string composed of characters having all a special meaning.

● To mark the start of optional parameter(s), a pipe (“|”) character is used.

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 pointer

Z zval**

Callback f zend_fcall_info, zend_fcall_info_cache

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

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)

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

OpenGrok (1/2)

● Your best friend to browse PHP's source code:http://lxr.php.net/

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

OpenGrok (2/2)

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

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;

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

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

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

Access macrosZ_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.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

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

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

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

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);

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

Exercise two: solutionPHP_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"); }}

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

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

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

PHP life cycles - CLI

● Credits: Extending and Embedding PHP by Sara Golemon (2006 June 9th)

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

PHP life cycles – Web server(prefork)

● Credits: Extending and Embedding PHP by Sara Golemon (2006 June 9th)

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

PHP life cycles - Web server(multi thread)

● Credits: Extending and Embedding PHP by Sara Golemon (2006 June 9th)

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

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

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

Exercise three: MyClass (2/10)

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

Exercise three: MyClass (3/10)

● http://tinyurl.com/PHP-ext-MyClass-1

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

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();

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

Exercise three: MyClass (5/10)

● http://tinyurl.com/PHP-ext-MyClass-2

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

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

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

Exercise three: MyClass (7/10)

● http://tinyurl.com/PHP-ext-MyClass-3

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

Exercise three: MyClass (8/10)

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

Exercise three: MyClass (9/10)

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

Exercise three: MyClass (10/10)

● http://tinyurl.com/PHP-ext-MyClass-4

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

Questions?

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

Thanks● Don't forget to rate this workshop on https://joind.in/6386


Recommended