Saturday, 8 November 2014

Future Notes

Fig 1. Go PHP "7"

Now that the master branch of PHP (PHP7) is stabilizing, it is time for those of us who maintain extensions to think about beginning the task of upgrading the source code to work with new API's and conventions in PHP7.

Without going into too much detail about why PHP7 is the way it is, I'm going to go through the major differences extension maintainers or authors need to be aware of.

The Zend Object

Those of us that don't hate our users provide Object Orientated API's, you might say that from the offset PHP7 is different.

When an extension registers a class entry in the MINIT routine, it sets a handler named create_object.

A typical create_object handler for a 5 series extension looks something like:

Every little counts, the fact that objects can accessed with pointer arithmetic is super cool, and saves many calls to zend_objects_store_get_object for even the simplest extension.

The only other thing to remember is Zend needs to know the offset of the zend_object in your objects structure, if zend_object is not the first member the offset should be stored in the objects handlers at the field named offset. This is typically done during MINIT when handler structures are first created by the extension.

Levels of Indirection

While we are C programmers, and so have intricate knowledge of pointers with triple indirection, indirection has an undeniable cognitive overhead. Many levels of indirection makes it harder to read and debug code, and in my opinion one of the best improvements in PHP7 is to drop the convention that it's okay to work with pointers with many levels of indirection.

This effects everything, from the fact that Z_*_PP macros no longer exist, to the HashTable and other Zend API's having significant changes.

HashTable and Strings

Hash tables are a staple of any extension, and Zend. The API has always felt like it was a compromise, and I'm pleased to observe that PHP7 finally has a nice HashTable API.

The first obvious change is where API functions used to take a char * and an int to represent a string and it's length respectively, PHP7 makes use of the zend_string structure for keys.

The zend_string structure in PHP7 can be refcounted and have hashes pre-calculated, rather cool.

If we look at PHP5 code that performs the familiar operation of fetching from a HashTable:

Note that zend_parse_parameters has a new type specifier for a zend_string*.

Sometimes a zend_string will not be available, and it may be inefficient to create one for a lookup or some other HashTable operation, for these cases the HashTable API has a set of functions with _str_ in their name, for example, zend_hash_str_find, which still accept a char* and a size_t.

Where to start ?

I have provided a brief explanantion of the main differences effecting extension maintainers in PHP7, some people might be able to get started with just this information.

I don't know how anyone else learned how to program for Zend, but personally, I read code.

Now is a good time to dig around in some of the headers so you can see in detail what has changed: