One of the most common reasons people write extensions for PHP is to link against an external library and make available its API to PHP userspace scripts. Often the external library is written in C or C++. If you are tasked with writing such an extension that links against an object oriented C++ library, you will probably want to wrap the C++ classes and make them available to PHP userspace scripts. This is pretty easy to do once you get over a few initial hurdles.
In this tutorial I am going to walk you through creating a PHP extension called "vehicles" which will expose a single class called "Car" (obviously in the real-world, your extensions will expose many classes, but I’m trying to keep things simple). The extension will be built for PHP 5. I am only going to give instructions for building the extension in a UNIX-like environment, although most of what I cover should apply to Windows extension development as well. Most of what I detail here will be an expanded or simplified version of material covered in the somewhat abandoned Using C++ With PHP. I am not going to cover the basics of PHP extension writing, for that I recommend Sara Goleman’s Extension Writing series or her book Extending and Embedding PHP.
File Layout
The extension you will be creating consists of several files which you should place in a directory called vehicles:
car.h - Contains the definition of the C++ Car class. car.cc - Contains the implementation of the C++ Car class. php_vehicles.h - Contains PHP specific includes, external variables, etc. vehicles.cc - The main source file of the extension. This will contain the PHP Car class. config.m4 - PHP Build system / autoconf configuration file.
Configuring the PHP Build System
In order to use C++ in your PHP extension, you must instruct the PHP build system to use a C++ compiler. This is done by calling the PHP_REQUIRE_CXX() macro in your config.m4 file. PHP_REQUIRE_CXX() is defined in aclocal.m4 in the root directory of the PHP source distribution and wraps the autoconf macro AC_PROG_CXX(), which is documented here. You must also link the C++ standard library (libstdc++ on most systems), which is done with the PHP_ADD_LIBRARY() macro. Put the following in your config.m4 file:
PHP_ARG_ENABLE(vehicles, [Whether to enable the "vehicles" extension],
[ --enable-vehicles support])
Enable "vehicles" extension
if test $PHP_VEHICLES != "no"; then
PHP_REQUIRE_CXX() PHP_SUBST(VEHICLES_SHARED_LIBADD) PHP_ADD_LIBRARY(stdc++, 1, VEHICLES_SHARED_LIBADD) PHP_NEW_EXTENSION(vehicles, vehicles.cc car.cc, $ext_shared) fi
Depending on your compiler and how you compiled PHP, you may have to wrap your includes and certain macros in a linkage specification. If you’re not sure what that means, this article explains it nicely. So, together with all the usual skeleton code for a PHP extension, your php_vehicles.h header file should look something like this:
#ifndef PHP_VEHICLES_H #define PHP_VEHICLES_H
#define PHP_VEHICLES_EXTNAME
"vehicles" #define PHP_VEHICLES_EXTVER "0.1"
#ifdef HAVE_CONFIG_H #include "config.h" #endif
extern "C" { #include "php.h" }
extern zend_module_entry vehicles_module_entry; #define phpext_vehicles_ptr &;vehicles_module_entry;
#endif /* PHP_VEHICLES_H */
Additionally, you’ll probably need to wrap the call to the ZEND_GET_MODULE() macro in vehicles.cc in a similar linkage specification. With that in mind, your vehic