The general idea of PHP scripts and extensions.

PHP is an interpreted script computer language, which calls functions and object methods defined in C-API extension methods for class methods and functions. Many extensions supply functionality across many domains and are distributed along with the core PHP interpreter source.

There are currently about 80 extensions, counting the names of sub-folders in the "ext" folder. There are many other useful and competent extensions available as 3rd party libraries.

Extensions are organized shared libraries (*.so in linux), that share their public data and functions with each other and the process that loads them.

Many compiler technologies exist to produce shared libraries. PHP is compile C language source code. Extensions can be written directly in C.

All those PHP API C macros - give me Zephir

Zephir is a PHP extension building script that parallels PHP script features and compiles to C source code. It was created because directly compiling PHP extensions, that are complex with a large number of classes, such as the Phalcon PHP classes bundle, is tedious, and slow in low level C.

Zephir source does have a degree of inflexibility and the generated C code looks machine generated, that is even harder than normal to read as C source. It is almost as flexible and productive as real PHP source.

PHP-CPP

PHP-CPP is a C++ class framework to build a shared library and PHP API extension classes and functions. Therefore C++ can be used to hide PHP low level complexity. Can PHP-CPP framework be improved?

PHP binary API

PHP script functions and class methods are shared C functions coded in extensions, with their names and arguments registered by each extension module so that they are callable from the PHP interpreter engine.

The full source of every published PHP version ever is downloadable as the "php-src" git repository on github. Types are in the zend_types.h file in the Zend folder. zend_types.h

Get the best code execution level

The aim of writing an extension is to provide efficient functions and object methods that improve on the the best script byte code interpreter, or JIT compiler, and hard-code into compiled native binary executable code. Extensions can link to other system libraries that support C-APIs and provide access to new and extended functionality.

How PHP exchanges data

Data is exchanged between interpreted and compiled code through exchanges of data managed by zval structures. These are passed directly through function arguments, and return values, in the zend_execute_data structure.

PHP provides C-Macros to check function arguments and further checked to extract some of the reference counted handle types. zend_string*, zend_object*, and HashTable* can already be directly extracted from zend_execute_data, by using ZEND_PARSE_PARAMETERS_START macro, found in zend_API.h.

Also found in this zend_API.h header, are C structures to assist calling other PHP functions and class methods, these are _zend_fcall_info_, and _zend_fcall_info_cache_. ZPP makes use of these in its zpp::fn_call and zpp::fun_call_args<T> structure declarations. Repeated use of the same call will speed the call using the cached reusable call data.

Usefulness of extensions

Apart from calls to and from the PHP API, the idea is that extension C/C++ code works with raw data structures of numbers, strings, and data storage, for which such compiled languages are designed. PHP strings and array storage is useful to use directly.

Array storage requires zval fetch and store, for the HashTable* API, and this is excellent for many purposes, as these are the all-purpose data store used in PHP scripts.

Object API and method calls is used extensively for services coordination between objects. Having underlying C++ objects in an extension, allows fast inter-object classes coordination to bypass the script engine. When extension objects provide really useful services, exposing classes and functions joins the community of useful extensions in PHP script space.

Extension source code

Many standard extension implementations distributed with PHP. This make PHP a rich, productive and efficient scripting environment. Inside, there are many zend API calls, many thousands of lines of source code. Deciphering it all can take a long time, even for a C-language expert.

Starting with C

There are beginner guides online, all assume that naturally PHP extensions are coded in C. There is some scattered information about for building a PHP extension using C++. I made use of the Zend - Perforce online guide as a beginner to building my first version of a PHP extensions in C, so I have been a while on that long journey. The current online link is Writing PHP Extensions,

Moving to C++

C++ can directly use the PHP C header files, and C++ will directly use the PHP source of structures, functions and macro constructions imported with extern "C". It therefore should be easy. C++ is a superset of C, so no problems? Right?

What follows will be what I learned as I coded a C++ extension for PHP to make useful classes for an efficient web-site framework. This is the PHP C++ Classes framework. I want to make these classes known, so they can be used and improved.

Merely "hard-coding" a framework as a shared library, does not by itself ensure execution efficiency.

Web Classes C++ extension

This Wcc framework objects also exists as pure PHP-script, which is backup for the same functionality, if the extension is not loaded. Wcc is an anacronym for "Web Classes C++ extension".

The framework can be used as PHP script code, no C++ extension necessary. The classes in PHP-script form have the same name and methods, and work the same, although some overall execution time increase can be measured.

The Wcc classes structure and design are I hope, reasonably efficient in terms of using the PHP environment, and achieving performance and usability goals. The script versions of the classes will not be loaded by the PHP engine, when the classes are already loaded as the C++ extension. Wcc is the namespace, and the extension name.

Extensions can't be overridden by scripts

When an extension version of any PHP class is already loaded, obviously the PHP engine does not call registered loaders to look for a script version. A forced load will produce an error.

  • The documentation of the derived classes is easier using tools that read the PHP script versions. But the underlying C++ PHP access classes that make them possible, need a separate document, as done here.

  • The Wcc extension objects API replicates a subset of the classes of the script version. They have the same class names and method names. Extension library users do not need to change any script code to use either. When using a PHP extension, script versions of the same class are not loaded. This also means that there are some classes that are required from the script version of the framework, that are not in the C++ extension, either because they provide important functionality not easily available from inside C/C++ extension, as "complementary classes", or they have not yet been coded in C++, and that this may be tried in the future.

  • The difference between script-only and using the extension is performance, as measured by memory usage, and execution speed, stability and systems code sharing. More built in classes can reduce PHP execution load time, presuming they are always needed. The PHP interpreter work includes dynamic reading script files, conversion into byte code, and then execution. All this takes up extra memory and processing time. Various cache mechanisms can be used to reduce script reading time and compile, execution memory overhead. The Wcc extension classes are for web site processing tasks, such as module,route, and template management, and gets a speed up of 60-70% of the time compared script versions.

  • The Wcc objects are coded and compiled in a typical, PHP generated, C-extension development environment that is a modified C extension development environment. The C arginfo interfaces, used to register classes and functions into PHP, are generated from the same PHP stubs function - class - method files. Only the C++ compiler is used instead of a C compiler. This is specified by a editing a few lines in the "config.m4" that is used to auto generate "configure" script and a Makefile.

  • The C++ extension, and the PHP script classes version of them were co-evolved, to ensure compatibility. Opportunities for improvement needed to be managed in both.

I had designed and tested these classes already in PHP, and I wanted to find out how much performance might improve when the PHP classes are implemented as "internal classes" using C++.

There are many popular PHP script web frameworks out there. All of them keep improving and hopefully display some conversion with current standards and best practices. However there is a contrary tendency with software development to building larger code bases with increasing complexity and obscure APIs.

There are many operations and computing resources not efficiently implementable at the level of PHP script code, because of, as well as despite its flexibility and forgiving nature.

C++ extensions improve on native PHP performance. Many of the "standard" extensions exist because of this, such as the regular expression functions and database interfaces. They take advantage of linking to task optimized algorithms in compiled machine code in external libraries. For example the regular expression string functions of PHP are provided by PCRE, the Pearl Compatible Regular Expressions library, and scripts have benefitted from its upgrades. PHP source builds can choose (or not) to incorporate external library versions distributed along with the php-src archive.

Extensions with Scripted Helper classes

"Extract" is a PHP Engine linked function used to push an associatred array of arbitrary keyed data into the symbol table of a current executing scripted function.

Extract is very useful for Php-Html templates. Extension functions do not have access to this, no surprise as their stack is their own native code binary, and breaking stack function call discipline of the callee is unthinkable. Closures cannot yet be consstructed by an internal class. Extension classes can implement an "Invoke method". These restrictions are circumvented by callbacks provided by the executing script.

When hard coded as an extension, classes are marked as "internal classes" by the Zend Engine. These are privileged classes regarding the Zend API, but there is some API functionality, that is not available, or is more difficult for an "internal" class. Examples of necessary but simple helper classes written as PHP script in the Wcc suite are the Wcc\Loader class and the Wcc\ViewOuput class.