Getting Started with PHP Extension Development via PHP-CPP — SitePoint – SitePoint
In your dealings with PHP, you may come to consider writing a PHP extension yourself. There are several reasons I can think of that motivate me to do so:
When it comes to choosing a tool to build PHP extensions, we see two different approaches:
For me, the main drive to select the second approach is simple: I started my programming hobby with C/C++, so I still feel more comfortable writing those lower level modules in C/C++. PHP-CPP’s official site gives a few other reasons to do so.
PHP-CPP is evolving rapidly. At the time of this article’s writing, it is in version 0.9.1 (with 0.9.0 released about 2 days before). According to its documentation, “this is a feature-freeze release that prepares for the upcoming v1.0 version”, so we are confident we’ll see its 1.0 major release very soon.
It is thus recommended, at least during this interim period, to use
git
to clone the repository and get the latest update later via git pull
. NOTE: The PHP-CPP documentation on installation states that for the time being, it “only supports single-threaded PHP installations” because “internally the Zend engine uses a very odd system to ensure thread safety”. Future releases may support multi-threaded PHP installations but let’s just keep this in mind for now and stick to its current limitation. Luckily, “single-threaded PHP installations” should be the case for most of the PHP installations out there.
PHP-CPP is written in C++11. Thus, the older version of g++ installed in my Ubuntu 12.04 LTS does not support it. We need to upgrade our g++ compiler to version 4.8.x above. There is an article detailing the steps to do the upgrading. Please follow the instructions listed there.
Also, PHP-CPP compilation will use the
php.h
header file. This file is normally missing in an Ubuntu box, unless php-dev
was installed. We can install PHP5 related development files by issuing this command: After upgrading g++ and installing the necessary header files, we can issue the following command to compile and install the PHP-CPP library file (
libphpcpp.so
):The compilation will be quite fast. After the installation, the
libphpcpp.so
file will be copied over to /usr/lib
, and all PHP-CPP header files will be copied to /usr/include
and /usr/include/phpcpp
folders.The installation of PHP-CPP lib is now complete. It is quite straightforward and we can now move on to the programming part.
Before we do that, we’ll discuss a few important concepts and terminologies used in PHP-CPP. The full documentation can be found on its official site, and everyone is encouraged to read through it BEFORE doing any real programming.
PHP-CPP provides a skeleton extension project, containing the following 3 files:
If you are familiar with *nix development, you are familiar with this Makefile. Some slight changes shall be made to customize this file to fit our needs:
These are all the changes I have made. The rest of the
Makefile
can be kept as it is. I renamed this file to
skeleton.ini
and changed the only line in that file like this:In the empty project provided by PHP-CPP, this file contains only one function:
get_module()
, which is excerpted below:For now, let’s just change this line to match the extension name we intend to create:
get_module()
is called by PHP when the latter tries to load a required library. It is considered the entry point for a lib. It is declared using the extern "C"
modifier to comply with PHP lib requirement for the get_module()
function. It also uses a macro PHPCPP_EXPORT
which makes sure that get_module()
is publicly exported, and thus callable by PHP.So far, we have made some changes to the empty project to suit our needs. We can now compile and install this project and install the extension:
Next, we need to copy the required files into the appropriate folders:
We just need to make sure that the
skeleton.so
lib is copied to the right location of PHP extensions (in my Ubuntu setup, it should be /usr/lib/php5/20121212
as shown above). We can then verify the extension is loaded in CLI by
php -i | grep skeleton
, and the terminal shall display something like this:(Recall that the
skeleton.ini
is the file we modified above, which contains the extension=skeleton.so
line.)We have so far compiled and installed our first PHP extension using PHP-CPP. Of course, this extension does nothing yet. We will now create our first few functions to further understand the process of building PHP extensions.
The first function we create will be a slightly modified version of “Hello, World”. Let’s see the full code of
main.cpp
first:According to the PHP-CPP documentation on “Register native functions“, it supports four types of function signatures to be called from PHP:
In this case, I am using the second signature and the parameters are passed by value in an array form (PHP feature).
However, in
helloWorld
, we have specifically used C++ type std::string
to grab the first parameter. We have also used C++ std
lib to output a welcoming message. In
get_module()
function, after declaring the extension
variable, we add the function we would like to export (helloWorld()
) and assign a name visible to the PHP script (helloWorld
). Now let’s compile and install the extension. If everything goes smoothly, the new
skeleton.so
file will be copied to the extension directory. We can write a simple script to test the function just created:
Please take some time to look at the output:
We will come back to what we have observed here later.
Next, we will see another function which passes parameters by reference, a
swap()
function. In this function, we will also try to specify the number of parameters and their type. In
main.cpp
, we add one more function swap()
:And also export the function by specifying the number of parameters and their type:
We explicitly say that:
Let’s compile and install the updated extension again and write some code snippets to see how this new functions works:
swap($a)
will fail. This is expected and unexpected. The expected part is that we need two parameters and only one is given. But, shouldn’t that error be captured by PHP when calling the function swap
and prompting us something like Not enough parameters
?The first call (
swap($a, $b)
) shows the expected result: 20|10
. The function swaps the two numbers passed in. The second call is somehow unexpected: we have told PHP that we are to swap two numbers! But it just ignores the fact that the 2nd parameter passed is a string and does the swapping anyway!
Well, in a way, it is still expected. PHP does not really distinguish a number type and a string type. This behavior complies to the PHP standard. Also due to this behavior, we didn’t and can’t use C++ internal types for the temporary variable used in the function (
temp
) but used Php::Value
as the variable type. The third call will work. The first
var_dump
will show the DateTime object and the second will show the integer. This is somehow very much unexpected (at least to me). After all, an object is quite different from a number/string. But after considering that this “swap” behavior is also doable in PHP, it fits in with PHP’s oddities. So, does it mean the “type” specification won’t have any impact? Not really. To further elaborate this, we create a third function:
And we register this function like this:
The testing code will be like this:
The first call to
swapObject()
will work as we passed in the correct class type (sampleClass
). The second will fail, displaying “PHP Catchable fatal error: Argument 1 passed to swapObject() must be an instance of sampleClass, instance of anotherClass given...
“. The above code segment illustrates one important aspect on type restriction: scalar types declaration is not really implemented. PHP and thus PHP-CPP only enforce object-type declaration. Also, the number of parameters is not really enforced on the PHP side.
In this article, we illustrated the steps to prepare PHP-CPP to work for our PHP environment. We also discussed some basic steps to create a PHP extension using PHP-CPP (and C++ semantics).
We covered the extension project files, function signatures, function export/registration, and the function parameter types.
In our next article, we will further elaborate a few key features in PHP-CPP and provide a real-world use case demonstrating the usage of C++ class and namespace implementations using PHP-CPP.
PHP-CPP is a library for developing PHP extensions. It offers a collection of well-documented and user-friendly classes, allowing C++ developers to write PHP extensions without the complexities of working directly with the Zend API. Unlike PHP, which is an interpreted language, PHP-CPP allows you to write code in C++, a compiled language. This can result in performance improvements, as compiled code generally runs faster than interpreted code.
To install PHP-CPP on your system, you need to clone the PHP-CPP repository from GitHub. After cloning, navigate to the directory and execute the ‘make’ command. Once the build process is complete, install the library using the ‘make install’ command. Remember, you need to have root privileges to install the library.
Creating a PHP extension using PHP-CPP involves several steps. First, you need to create a directory for your extension and navigate into it. Then, create a ‘Makefile’ and a C++ source file for your extension. The ‘Makefile’ will contain instructions for building your extension, while the C++ source file will contain the actual code for your extension. After writing your code, you can build your extension using the ‘make’ command.
Debugging a PHP extension can be a bit tricky, as you’re dealing with a compiled language. However, you can use tools like GDB (GNU Debugger) to debug your extension. GDB allows you to set breakpoints, step through your code, and inspect variables, which can be very helpful when trying to track down bugs.
Yes, PHP-CPP is compatible with PHP 7. However, you need to make sure that you’re using the latest version of PHP-CPP, as earlier versions may not support PHP 7.
PHP-CPP provides a class called Php::Exception, which you can use to throw exceptions from your C++ code. These exceptions can then be caught and handled in your PHP code, just like any other PHP exception.
Yes, PHP-CPP supports object-oriented programming. You can define classes in your C++ code, and these classes can then be used in your PHP code. This allows you to write clean, modular code that’s easy to maintain.
PHP-CPP provides a class called Php::Call, which you can use to call PHP functions from your C++ code. This allows you to leverage the power of PHP’s built-in functions in your extension.
Yes, you can use PHP-CPP to create extensions that interact with databases. However, you’ll need to use a C++ database library, as PHP-CPP does not provide any built-in database functionality.
Once you’ve built your PHP extension, you can distribute it by packaging it as a PECL package. PECL is a repository for PHP extensions, and it provides a standard way to distribute and install extensions.
Taylor is a freelance web and desktop application developer living in Suzhou in Eastern China. Started from Borland development tools series (C++Builder, Delphi), published a book on InterBase, certified as Borland Expert in 2003, he shifted to web development with typical LAMP configuration. Later he started working with jQuery, Symfony, Bootstrap, Dart, etc.
© 2000 – 2024 SitePoint Pty. Ltd.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
source