Ever been interested by contributing to the PHP core team?
In this workshop you will not only learn how (easy it is) to create your own PHP extension from scratch but you will also strengthen your knowledge of PHP by disecting its internals.
After this workshop, you will be able to create an extension on your own, whether it is to optimize the most CPU intensive parts of your code, to create new bindings to C libraries or just to leverage your PHP knowledge.
And what if PHP was a web framework for the C developer?
This workshop requires a bit of C knowledge and preferably a *nix system.
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
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
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
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
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
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();
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