Translate: 
EnglishFrenchGermanItalianPolishPortugueseRussianSpanish

How to create PHP extensions – part I: simple functions

There are some situations when every developer encounters limitations in PHP. For some, the problem is performance, for others the lack of specific, low-level functionality.

In that cases, the only solution is to write your own PHP extension that adds the missing features to the language.

Unfortunately, although the documentation of the PHP language itself is excellent, the information on the programming of the PHP engine are rudimentary.

In this series of articles I will try to show you, how to write the PHP extensions and describe some of the Zend engine features.

System Requirements

In order to create your own PHP extensions, you’ll need PHP itself, and the set of build tools required by PHP: a C compiler (for example: gcc), PHP developer tools (phpize, php-config, source code files) and a simple text editor.

On Fedora and CentOS systems, required packages can be installed using following command:

$ yum install gcc php php-devel

Required files

Zend Engine requires at least two different files. The first required file is called config.m4. It stores the basic configuration data used by the PHP to compile your custom extension.

Let’s look at it’s contents:

PHP_ARG_ENABLE(my_extension, whether to enable my extension,
[ --enable-my-extension   Enable my extension])
 
if test "$PHP_MY_EXTENSION" = "yes"; then
  AC_DEFINE(HAVE_MY_EXTENSION, 1, [Whether you have my extension])
  PHP_NEW_EXTENSION(my_extension, my_extension.c, $ext_shared)
fi

This file is used by a phpize tool (which I’ll describe later in this article). As you can see, among many different information it also specifies the name of file to be compiled. That is the second required file, because it contains the source code, that extends the PHP language.

In this case, the source code file is called my_extension.c. Here are its contents:

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
 
#define PHP_MY_EXTENSION_VERSION "1.0"
#define PHP_MY_EXTENSION_EXTNAME "my_extension"
 
extern zend_module_entry my_extension_module_entry;
#define phpext_my_extension_ptr &my_extension_module_entry
 
// declaration of a custom my_function()
PHP_FUNCTION(my_function);
 
// list of custom PHP functions provided by this extension
// set {NULL, NULL, NULL} as the last record to mark the end of list
static function_entry my_functions[] = {
    PHP_FE(my_function, NULL)
    {NULL, NULL, NULL}
};
 
// the following code creates an entry for the module and registers it with Zend.
zend_module_entry my_extension_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
    STANDARD_MODULE_HEADER,
#endif
    PHP_MY_EXTENSION_EXTNAME,
    my_functions,
    NULL, // name of the MINIT function or NULL if not applicable
    NULL, // name of the MSHUTDOWN function or NULL if not applicable
    NULL, // name of the RINIT function or NULL if not applicable
    NULL, // name of the RSHUTDOWN function or NULL if not applicable
    NULL, // name of the MINFO function or NULL if not applicable
#if ZEND_MODULE_API_NO >= 20010901
    PHP_MY_EXTENSION_VERSION,
#endif
    STANDARD_MODULE_PROPERTIES
};
 
ZEND_GET_MODULE(my_extension)
 
// implementation of a custom my_function()
PHP_FUNCTION(my_function)
{
    RETURN_STRING("This is my function", 1);
}

Most of the preceding code serves as a template for any PHP extension (usually, during the further development, this template does not change at all). In fact, there are only two short pieces of code that implement new, custom PHP features:

PHP_FUNCTION(my_function);
 
static function_entry my_functions[] = {
    PHP_FE(my_function, NULL)
    {NULL, NULL, NULL}
};

and

PHP_FUNCTION(my_function)
{
    RETURN_STRING("This is my function", 1);
}

The first code adds my_function() to the list of available functions in PHP using a PHP_FE macro, while the second code contains the body of your own PHP function.

In this case my_function() returns a “This is my function” string. For this purpose, it uses the RETURN_STRING macro. First parameter of this macro accepts the contents of a string, while second tells the Zend engine if this string should be returned by copy or by reference.

If you wish to return a different scalar type of data instead of a string, you can use following set of macros:

RETURN_BOOL(x);
RETURN_LONG(x);
RETURN_DOUBLE(x);
RETURN_NULL();

For example, you can redeclare my_function() to return the value of PI, like so:

PHP_FUNCTION(my_function)
{
    double _pi = 3.1415926535;
    RETURN_DOUBLE(_pi);
}

Building the extension

To initiate the compilation, type the following commands inside of your extension’s directory :

$ phpize
$ ./configure
$ make install

The phpize command will generate additional configuration files, required to compile your PHP extension (you can reverse this process anytime by typing the “phpize –clean” command).

After running each of these commands, you should have a my_extension.so file in PHP extensions directory. If don’t know the name of that directory, you can check it’s name by typing:

$ php-config|grep extension-dir

The last thing you need to do, is to add the following line to your php.ini to load your extension on PHP startup:

extension=my_extension.so

For CGI/CLI, this will be the next time PHP script is run, and for web servers (like Apache), this will be the next time the web server is restarted.

Please note, only “make install” is needed to rebuild your already configured PHP extension. You can safely skip phpize and ./configure commands. They are required only in two cases: during the first compilation, or if a config.m4 file has been modified since the last build process.

Testing the extension

You can test your PHP extension by typing the following command:

$ php -r "echo my_function();"

If everything was fine, the output will be:

This is my function

What’s next?

In my next article I will demonstrate some basic operations on PHP variables.

Tags:

4 Responses to “How to create PHP extensions – part I: simple functions”

  1. Andre says:

    Thanks in advance. This is a great serie. Waiting part 2. :-) Thanks.

  2. Blogi says:

    I need your help. I like your blog. Your texts are interesting. I got here by mistake and I started reading. I became interested in the topic and I am thinking whether I could use your texts on my paper, only with the quotation. Please write me back, thanks very much.

  3. Sathishkumar says:

    Thanks a lot, Its working

    Can you please tell me how to test it

    I have compiled bcmath extension as like you said, the file was created in /usr/lib64/php/modules/bcmath.so

    Now i wann to test it. I have test like this

    php -r “echo bcmath();”
    PHP Fatal error: Call to undefined function bcmath() in Command line code on line 1

    I am novice in PHP..

    Thanks in advance

  4. I’ve upgraded to PHP 5.4.4, and when I run “make” for the sample code above, I get the following error:

    error: syntax error before “my_functions”

    Did the API change for php 5.4? I have run this on PHP 5.3 without problems.

Leave a Reply