PHP: Creating Extensions - Manual

downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Using Extensions PHP's Automatic Build System

Last updated: Fri, 26 Jan 2007

view this page in

# Creating Extensions

We'll start with the creation of a very simple extension at first, which basically does nothing more than implement a function that returns the integer it receives as parameter. Прим. 46-2 shows the source.

Пример 46-2. A simple extension.

    /* include standard header */
    #include "php.h"

    /* declaration of functions to be exported */
    ZEND_FUNCTION(first_module);

    /* compiled function list so Zend knows what's in this module */
    zend_function_entry firstmod_functions[] =
    {
        ZEND_FE(first_module, NULL)
        {NULL, NULL, NULL}
    };

    /* compiled module information */
    zend_module_entry firstmod_module_entry =
    {
        STANDARD_MODULE_HEADER,
        "First Module",
        firstmod_functions,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        NO_VERSION_YET,
        STANDARD_MODULE_PROPERTIES
    };

    /* implement standard "stub" routine to introduce ourselves to Zend */
    #if COMPILE_DL_FIRST_MODULE
    ZEND_GET_MODULE(firstmod)
    #endif

    /* implement function that is meant to be made available to PHP */
    ZEND_FUNCTION(first_module)
    {
        long parameter;

        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &parameter) == FAILURE) {
            return;
        }

        RETURN_LONG(parameter);
    }

This code contains a complete PHP module. We'll explain the source code in detail shortly, but first we'd like to discuss the build process. (This will allow the impatient to experiment before we dive into API discussions.)

> Замечание: The example source makes use of some features introduced with the Zend version used in PHP 4.1.0 and above, it won't compile with older PHP 4.0.x versions.

## Compiling Modules

There are basically two ways to compile modules:

- Use the provided "make" mechanism in the `ext` directory, which also allows building of dynamic loadable modules.

- Compile the sources manually.

The first method should definitely be favored, since, as of PHP 4.0, this has been standardized into a sophisticated build process. The fact that it is so sophisticated is also its drawback, unfortunately - it's hard to understand at first. We'll provide a more detailed introduction to this later in the chapter, but first let's work with the default files.

The second method is good for those who (for some reason) don't have the full PHP source tree available, don't have access to all files, or just like to juggle with their keyboard. These cases should be extremely rare, but for the sake of completeness we'll also describe this method.

Compiling Using Make. To compile the sample sources using the standard mechanism, copy all their subdirectories to the `ext` directory of your PHP source tree. Then run `buildconf`, which will create an updated `configure` script containing appropriate options for the new extension. By default, all the sample sources are disabled, so you don't have to fear breaking your build process.

After you run `buildconf`, `configure --help` shows the following additional modules:

    --enable-array_experiments   BOOK: Enables array experiments
      --enable-call_userland       BOOK: Enables userland module
      --enable-cross_conversion    BOOK: Enables cross-conversion module
      --enable-first_module        BOOK: Enables first module
      --enable-infoprint           BOOK: Enables infoprint module
      --enable-reference_test      BOOK: Enables reference test module
      --enable-resource_test       BOOK: Enables resource test module
      --enable-variable_creation   BOOK: Enables variable-creation module

The module shown earlier in Прим. 46-2 can be enabled with `--enable-first_module` or `--enable-first_module=yes`.

Compiling Manually. To compile your modules manually, you need the following commands:

Action | Command
Compiling | cc -fpic -DCOMPILE_DL_FIRST_MODULE=1 -I/usr/local/include -I. -I.. -I../Zend -c -o `<your_object_file>` `<your_c_file>`
Linking | cc -shared -L/usr/local/lib -rdynamic -o `<your_module_file>` `<your_object_file(s)>`

The command to compile the module simply instructs the compiler to generate position-independent code (`-fpic` shouldn't be omitted) and additionally defines the constant `COMPILE_DL_FIRST_MODULE` to tell the module code that it's compiled as a dynamically loadable module (the test module above checks for this; we'll discuss it shortly). After these options, it specifies a number of standard include paths that should be used as the minimal set to compile the source files.

Note: All include paths in the example are relative to the directory `ext`. If you're compiling from another directory, change the pathnames accordingly. Required items are the PHP directory, the `Zend` directory, and (if necessary), the directory in which your module resides.

The link command is also a plain vanilla command instructing linkage as a dynamic module.

You can include optimization options in the compilation command, although these have been omitted in this example (but some are included in the makefile template described in an earlier section).

Note: Compiling and linking manually as a static module into the PHP binary involves very long instructions and thus is not discussed here. (It's not very efficient to type all those commands.)

add a note User Contributed Notes
Creating Extensions
vijay at planetbazaar dot com
17-Sep-2005 12:53
`Notes for Windows PHP5 extension developers:
First, two great articles at http://www.zend.com/php/internals/index.php are in the must read category. Unfortunately an article on building extensions on Windows is yet to arrive at this time. So one gets stuck at section 'Building Your Extension' in the first article - because there is no 'phpize' for Windows to the best of my knowledge.
First point of curiosity is how the extensions that are available for Windows appear in the output of "cscript /nologo configure.js --help". Turns out the magic happens by executing "buildconf.bat". To cut a long story short, it turns out that for Windows, the build system looks for config.w32 in each extension directory instead of config.m4; config.w32 is actually a javascript (from what I gather reading the "vim:ft=javascript" comment at the top of the files).
To get going with the "hello world" sample in the article mentioned above here is the config.w32 to replace config.m4;
--- begin file: config.w32 ---
// hello world module configuration
// vim:ft=javascript
ARG_ENABLE("hello", "hello Enable Hello World support", "no");
if (PHP_HELLO == "yes") {
EXTENSION("hello", "hello.c", null, "-Iext/hello");
AC_DEFINE('HAVE_HELLO', 1, 'Whether you ave Hello World');
}
--- end file: config.w32 ---
And just to compare, here is the config.m4
--- begin file: config.m4 ---
dnl vim:ft=m4
dnl hello world module configuration
PHP_ARG_ENABLE(hello, whether to enable Hellow World support,
[ --enable-hello Enable Hello World support])
if test "$PHP_HELLO" = "yes"; then
AC_DEFINE(HAVE_HELLO, 1 [Whether you have Hello World])
PHP_NEW_EXTENSION(hello, hello.c, $ext_shared)
fi
--- end file: config.m4 ---
And finally the key step is to execute 'buildconf.bat'; after this step:
cscript /nologo configure.js | find "hello"
should show something like:
"--enable-hello hello Enable Hello World support"`
josephmdaly at gmail dot com
29-Jul-2005 01:58
`It looks like PHP 5 uses a newer version of the windows socket library.
If your extension links to a library that uses the old version you might get a lot of errors about redefining things.
To fix this problem make sure the PHP header files are included before the library�s header files.`
seymour_levine at hotmail dot com
14-Jun-2005 05:18
`A small amount of administration is needed to make this work.
Mainly the dl command does not pick up the module created.
To remedy, use a full path for the extension_dir parameter in php.ini. Then create that subdirectory mod 755 vis:
extension_dir=/usr/lib/php411
And create php411. The name is arbitrary.
In the php dl command, specify dl('firstmod.so'); do not use any slashes.`
Sy Levine
13-Jun-2005 05:29
`I installed and run 4.1.1 on RH 7.1 It runs on a separate Apache Server than the one furnished by Red Hat.
A few adminisrative changes were necessary to get the function going.
The main one was finding and modifying php.ini.
The command: find . -print | grep php.ini should do that.
Mine was in /usr/local/lib
Look for extension_dir in php.ini then type the directive as
extension_dir=/usr/lib/php4
Use no trailing / in the directive. This is where the dl('firstmod.so') php statement accesses your module.
Tip: I do not use a leading / like dl('/firstmod.so') which will be misparsed. {Note by Ed a PHP ...}
The source module is named firstmod.c.
I compiled and created the firstmod.so with a script based on the various notes about the compile parameters. See
markjolesen, ywarnier, 17-Apr, wish I .`
davide dot chiodi at poste dot it
06-Apr-2005 10:34
`to build with lcc-win32 compiler:
change #include "php.h" to #include "php-lcc.h"
this is php-lcc.h (copied from excellent windbinder project by Rubem Pechansky)
//ZEND constants
#if defined(_MSC_VER) // Rick
# if defined(ZEND_EXPORTS)
# undef ZEND_EXPORTS
# endif
# undef ZEND_DEBUG
#else
# define PHP_WIN32
# define ZEND_WIN32
#endif
#define ZEND_DEBUG FALSE // Must be FALSE
#define ZTS // Must define ZTS (Zend Thread Safety)
#define PHP_REGEX_H // Skip php_regex.h: '_off_t' not defined anywhere
#define COMPILE_DL_FIRST_MODULE 1
//----------------------------------------------------------------- DEPENDENCIES
#include <php.h>
//---------------------------------------------------------- AUXILIARY FUNCTIONS
int parse_array(zval *array, const char *fmt, ...);
//------------------------------------------------------------------ END OF FILE
you must also used tweaked headers file from winbinder author at this link: http://hypervisual.com/winbinder/files/archived/php4_tweaked_headers.zip
(php 4).
I used php 4.3.10 and all worked fine`
ywarnier at beeznest dot org
25-Oct-2004 04:19
`Quick note to save time to beginners
To make the example above work, I had to add -I../TSRM because the file tsrm_virtual_cwd.h couldn't be found otherwise (it's located in the TSRM directory which is not included above)
In my case (pure Debian Woody install), php libraries were located in /usr/include/php4 (and php.h was in the 'main' subdirectory) so I had to use this path instead of /usr/local/include`
someone at apple
01-May-2004 10:55
`When following the directions for compiling via make, it may be necessary to delete the configure script before running buildconf. Otherwise you may get a complaint about buggy cache code and the configure script won't actually be updated.`
spsuhas at yahoo dot com
22-Jun-2003 01:23
`If you want to write extension for windows system, Take a look at this article
http://www.devnewz.com/2002/0909.html
It works!
Suhas`
Ed a PHP enthusiast from NYC
27-Apr-2003 10:55
`Thank you very much for the comments above!
Here is a distillation of how to compile your module as a dynamic library, placing it in your web server and loading it in your test .php file being served (PHP 4.3.1).
*** Compiling a module as a .so
$ cd ext/mystuff
$ cc -fpic -DCOMPILE_DL_MYSTUFF=1 -I/usr/local/include -I../../TSRM -I../.. -I../../main -I../../Zend -I../../ext/bcmath/libbcmath/src -c -o mystuff.o mystuff.c
$ cc -shared -L/usr/local/lib -rdynamic -o mystuff.so mystuff.o
*** Move it to the web server (doc root is /www)
$ cp mystuff.so /www/.
$ chmod 644 /www/mystuff.so
*** load the module in the .php file for testing purposes
<?
dl('/mystuff.so');
/* your php code here */
?>
The other thing that threw me off my tracks is that when dealing with strings you can allocate memory with emalloc and return the result with the RETURN_STRING macro (duplicate set to 0) and presumably PHP will take care of the efree -- or else I got it wrong and have plenty of leaks ;-)`
16-Apr-2003 11:08
`Compiling Manually NOTE:
remenber add -DHAVE_CONFIG_H flag
otherwise you .so can't be ld. then you cp it to php modules directory.
i.e
Compiling cc -fpic -DHAVE_CONFIG_H -I/usr/local/include -I. -I.. -I../Zend -c -o <your_object_file> <your_c_file>`
Mac M�hleisen
19-Mar-2003 11:55
`To built the modules shipped with the source just cd into the ext dir for example
cd ext/oci8
and type
export SHLIB_SUFFIX_NAME=so
phpize && aclocal && ./configure && make
now you have a subdir called "modules" with the .so file. Copy it to your extension dir and set everything up in php.ini.
This way you can add extensions to binary distributions like RPMS.`
add a note
Using Extensions PHP's Automatic Build System

Last updated: Fri, 26 Jan 2007
show source | credits | stats | sitemap | contact | advertising | mirror sites
Copyright © 2001-2007 The PHP Group
All rights reserved.
This mirror generously provided by: Yahoo! Inc.
Last updated: Sat Mar 10 10:36:09 2007 PST