An Introduction To The PH7 C/C++ Interface.
This article provides an overview and roadmap to the C/C++ interface to PH7.
Early versions of the PH7 engine were very easy to learn since they only supported 12 C/C++ interfaces. But as the PH7 engine has grown in capability, new C/C++ interfaces have been added so that now there are over 80 distinct APIs. This can be overwhelming to a new programmer. Fortunately, most of the C/C++ interfaces in the PH7 engine are very specialized and never need to be used. Despite having so many entry points, the core API is still relatively simple and easy to code to. This article aims to provide all of the background information needed to easily understand how the PH7 engine works.
A separate document, The PH7 engine C/C++ Interface, provides detailed specifications for all of the various C/C++ APIs for the PH7 engine. Once the reader understands the basic principles of operation for the PH7 engine, that document should be used as a reference guide. This article is intended as introduction only and is neither a complete nor authoritative reference for the PH7 API.
1.0 Core Objects And Interfaces
The principal task of a PHP engine is to compile and execute PHP code. In order to accomplish this purpose, the developer needs to know about two objects:
The PH7 engine handle: ph7
The PH7 virtual machine object: ph7_vm
PH7 engine Handle
typedef struct ph7 ph7;
Each active PH7 engine is represented by a pointer to an instance of the opaque structure named "ph7". It is useful to think of an ph7 pointer as an object.
There is also the ph7_config() interface which is used to configure a working ph7 engine.
The most important interfaces are the compile interfaces: ph7_compile(), ph7_compile_v2() and ph7_compile_file(). That is, these interfaces takes as their input a PHP program to compile and produces PH7 bytecodes represented by an opaque pointer to the ph7_vm structure (see below for more information on this structure).
PH7 virtual machine Object
typedef struct ph7_vm ph7_vm;
An instance of this object represents a compiled PHP program. this structure hold the PH7 bytecode program resulting from successful compilation of the target PHP script using one of the compile interfaces.
The life of a ph7 virtual machine goes something like this:
Compile your PHP script using one of the ph7_compile(), ph7_compile_v2() or ph7_compile_file() interfaces. On successful compilation, the PH7 engine will automatically create an instance of this structure (ph7_vm) and a pointer to this structure is made available to the caller.
When something goes wrong while compiling the PHP script due to a compile-time error, the caller must discard this pointer and fix its erroneous PHP code. Compile-time error messages can be extracted via a call to ph7_config().
Configure the virtual machine using the ph7_vm_config() interface with it's many configuration verbs, but the most important option is set via the PH7_VM_CONFIG_OUTPUT verb which is used to register a VM output consumer callback. That is, an user defined function responsible of consuming the VM output such as redirecting it [i.e: the VM output] to the standard output (STDOUT) or sending it back to the connected peer and so on.
Execute the compiled PHP program by calling ph7_vm_exec() one or more times.
Reset the virtual machine using ph7_vm_reset() then go back to step 5. Do this zero or more times.
Destroy the virtual machine using ph7_vm_release().
Refer to documentation on individual methods above for additional information.
The PH7 engine and the PH7 virtual machine objects are controlled by a small set of C/C++ interface routine listed below:
int ph7_init(ph7 **ppEngine);
int ph7_config(ph7 *pEngine,int nConfigOp,...);
int ph7_release(ph7 *pEngine);
int ph7_vm_config(ph7_vm *pVm,int iConfigOp,...);
int ph7_vm_exec(ph7_vm *pVm,int *pExitStatus);
int ph7_vm_reset(ph7_vm *pVm);
int ph7_vm_release(ph7_vm *pVm);
The ten C/C++ interface routines and two objects listed above form the core functionality of PH7. The developer who understands them will have a good foundation for using PH7.
Here is a summary of what the core interfaces do:
This routine create, initialize and returns a new PH7 engine instance. This is often the first PH7 API call that an application makes and is a prerequisite in order to compile PHP code using one of the compile interfaces.
To execute PHP code, it must first be compiled into a bytecode program using one of these routines.
These routine takes as their input a PHP program to compile and produce PH7 bytecodes represented by an opaque pointer to the ph7_vm structure.
These APIs does not actually evaluate the PHP code. They merely prepares the PHP code for later execution.
When something goes wrong while compiling the PHP script due to a compile-time error, the caller must discard the ph7_vm pointer and fix it's erroneous PHP code.
The compile-time error log can be extracted using the ph7_config() interface with a configuration verb set to:
After successful compilation of the target PHP script, this is the first API function you should call. This interface is used to configure a working virtual machine. There are so many configuration verbs but the most important is the PH7_VM_CONFIG_OUTPUT option. This configuration verb is used to register a VM output consumer callback. That is, an user defined function responsible of consuming the VM output such as redirecting it to the standard output (STDOUT) or sending it back to the connected peer and so on. Download and Compile this C file for a working example.
This routine is used to execute PH7 bytecode program resulting from successful compilation of the target PHP script using one of the compile interfaces. Download and Compile this C file for a working example.
This routine is used to reset the virtual machine to it's initial state so that the compiled program can be re-executed again.
This routine destroy a working PH7 virtual machine. Every virtual machine must be destroyed using a call to this routine in order to avoid memory leaks.
This routine destroy a working PH7 engine created by a prior call to ph7_init(). Every PH7 engine must be destroyed using a call to this routine in order to avoid memory leaks.
3.0 Typical Usage of Core Routines and interfaces
An application that wants to use PH7 will typically use ph7_init() to create a new PH7 engine instance. After that, to run PHP scripts,it must be first compiled to PH7 bytecode program using one of the compile interface such as ph7_compile(), ph7_compile_v2() or ph7_compile_file(). After successful compilation, the virtual machine should be configured using the ph7_vm_config() interface. Now call ph7_vm_exec() one or more times to execute your compiled PHP program. When done call ph7_vm_release() and ph7_release() to destroy respectively the virtual machine and the ph7 engine instance.
3.0 In-Process Extending
The ph7_create_function() interface is used to install a foreign function (typically a C/C++ function) that can be invoked from your PHP code. The new function implementation typically makes use of the following additional interfaces.
Refer to the following tutorial for a step by step guide on how to create, install and call foreign functions from your PHP code.
The ph7_create_constant() interface is used to associate a constant name (An identifier in the PHP world such as PHP_EOL, PHP_OS, PI, etc.) with a C callback that is responsible of expanding the constant name to the desired value such as 3,14 the value of PI.
Refer to the following tutorial for a step by step guide on how to create, install and expand constants from your PHP code.
4.0 Others Interfaces
This article only mentions the foundational PH7 interfaces. The PH7 library includes many other APIs implementing useful features that are not described here. A complete list of functions that form the PH7 application programming interface is found at the C/C++ Interface Specification. Refer to that document for complete and authoritative information about all PH7 interfaces.