extending php (7), the basics
TRANSCRIPT
Extending PHP (7.x)How to, when and when not
Pierre Joye@[email protected]://www.slideshare.net/pierrej
PHP Core developerContributors to numerous OSS projects
Portability fan
hiring@BK
Kdev – devops – sysops –
When to use custom extensions?
PHP 7 is fast.
PHP will be even faster.
OpCache rocks.
IOs are slow.
Streams are easy.
File Ops are easy.
zval
• Integer > zend_long
• Booleans > types, IS_TRUE/IS_FALSE
• Strings > zend_string
• Float > double
• Object > zend_object
• Resource
Hash Tables
• Array (zval > array > hash table)
• Functions table
• Classes, properties, etc.
Classes
• Classes declaration
Zend/zend_types.hyour best friend.
typedef struct _zval_struct zval;
struct _zval_struct {
zend_value value; /* value */
union {
struct {
ZEND_ENDIAN_LOHI_4(
zend_uchar type, /* active type */
zend_uchar type_flags,
zend_uchar const_flags,
zend_uchar reserved) /* call info for EX(This)*/
} v;
uint32_t type_info;
} u1;
....
};
Hash tables
Hash tables are not arrays!
Hash tables elements can contain ANYTHING
Zend/zend_hash.hYour second best buddy
Let get started
Requirements *nix
• Common• A shell
• editor
• Gcc 5+
• php7-dev
• Autoconf, autotools and co
Requirements Windows
• Common• A shell
• php-sdk (http://windows.php.net/downloads/php-sdk/)
• vc (14+) for Windows
• php binary tools (http://windows.php.net/downloads/php-sdk/)
• Setup your sdk structure according to https://wiki.php.net/internals/windows/stepbystepbuild
Extension directory structure
myextconfig.w32
Build script for windows
config.m4
Build script for *nix
php_myext.c
Implementation
php_myext.h
Interface & meta data
Tests
myext testsmyext.phpt
config.w32
// $Id$ // vim:ft=javascript
ARG_ENABLE("myext", "myext support", "yes");
if (PHP_MYEXT == "yes") {
EXTENSION("myext", "php_myext.c");
}
config.m4
dnl Tell PHP about the argument to enable the hello extension
PHP_ARG_ENABLE(myext, Whether to enable the myext extension, [ --enable-myext Enable myext])
if test "$PHP_MYEXT" != "no"; then
PHP_NEW_EXTENSION(myext, php_myext.c, $ext_shared)
fi
Our first function
function myext_hello() {
echo "Hello Manila!";
}
php_myext.h
#define PHP_MYEXT_EXTNAME "myext“
#define PHP_MYEXT_VERSION "0.0.1"
PHP_FUNCTION(myext_hello);
php_myext.c
#include <php.h>
#include "php_myext.h"
include php common interfaces and types
php_myext.c
Define myext_hello functions and commons hooks&data for myext
zend_function_entry myext_functions[] = {
PHP_FE(myext_hello, NULL)
PHP_FE_END
};
zend_module_entry myext_module_entry = {
STANDARD_MODULE_HEADER,
PHP_MYEXT_EXTNAME,
myext_functions,
NULL,
NULL, NULL, NULL, NULL,
PHP_MYEXT_VERSION,
STANDARD_MODULE_PROPERTIES,
};
zend_value
Define myext_hello functions and commons hooks&data for myext
typedef union _zend_value {
zend_long lval; /* long value */
double dval; /* double value */
zend_refcounted *counted;
zend_string *str;
zend_array *arr;
zend_object *obj;
zend_resource *res;
zend_reference *ref;
zend_ast_ref *ast;
zval *zv; void *ptr;
zend_class_entry *ce;
zend_function *func;
struct { uint32_t w1; uint32_t w2; }ww;
} zend_value;
php_myext.c
print „Hello Manilla!\n“ to php standard output
PHP_FUNCTION(myext_hello) {
php_printf("Hello Manila!\n");
};
First build
All platforms:
$ phpize
$ configure –enable-myext
For *nix flavors:
$ make
For Windows:
$ nmake
first function, with a string argument
function myext_print(string $mystring) {
echo "Hello " . $mystring . "!\n";
}
first function, with a string argument
PHP_FUNCTION(myext_print) {
char *mystring;
size_t mystring_len;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &mystring, &mystring_len) ==
FAILURE) {
return;
}
php_printf("Hello %s!! (%i)\n", mystring, mystring_len);
return
}
first function, with an integer argument
function myext_integer(int $myint) {
if ($myint > 0) {
for ($i = 0; $i < $myint; $i++) {
echo "Hello " . $i . "!\n";
}
}
}
first function, with an integer argument
PHP_FUNCTION(myext_print_integer) {
zend_long lval;
int i;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"l", &lval) == FAILURE) {
return;
}
if (lval > 0) {
for (i=0; i < lval; i++) {
php_printf("Hello %i\n",i);
}
}
return;
}
first function, with an array argument
function myext_print_array(array $myarray) {
foreach ($myarray as $val) {
echo "hello ". $val . "\n";
}
}
first function, with an array argument
PHP_FUNCTION(myext_print_array) {
zval *myarray = NULL;
zend_string *key;
zend_ulong num_key;
zval *val;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &myarray) ==
FAILURE) {
return;
}
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(myarray), num_key, key,
val) {
php_printf("Hello %s\n", Z_STRVAL_P(val));
}
ZEND_HASH_FOREACH_END();
return;
}
home work
• First class
• Zend Memory Manager• Use tools like valgrind
• Use external libraries
• Debugging using gdb or vs debugger
resources
• https://wiki.php.net/phpng-upgrading
• https://nikic.github.io/
• https://wiki.php.net/internals/
• http://www.phpinternalsbook.com/
• http://jpauli.github.io/
• https://github.com/php/php-src