PHP: Creating Extensions - Manual
PHP  
downloads | documentation | faq | getting help | mailing lists | | php.net sites | links | my php.net 
search for in the  
<PHP's Automatic Build SystemUsing Extensions>
view the version of this page
Last updated: Tue, 21 Dec 2004

第 47章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. 例47-1 shows the source.

例 47-1. 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 例47-1 can be enabled with --enable-first_module or --enable-first_module=yes.

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

ActionCommand
Compilingcc -fpic -DCOMPILE_DL=1 -I/usr/local/include -I. -I.. -I../Zend -c -o <your_object_file> <your_c_file>
Linkingcc -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 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 add a note User Contributed Notes
Creating Extensions
markjolesen at muchomail dot com
08-Dec-2004 10:17
To correctly compile the example source to use dynamic linking, change the compile flag  -DCOMPILE_DL to -DCOMPILE_DL_FIRST_MODULE. Otherwise, you'll get an invalid library when calling dl().
ywarnier at beeznest dot org
25-Oct-2004 11: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
02-May-2004 05: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.
Carl
02-Jul-2003 12:38
I had some problems with "undefined function".

Fatal error: Call to undefined function: csgetmap()
while trying to access by ZEND FUNCTION csGetMap

I the problem fixed it by making ALL FUNCTIONS LOWER CASE.
eg:
[SNIP------------------------------------------]

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

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

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

/* compiled module information */
zend_module_entry coreSO_module_entry =
{
   STANDARD_MODULE_HEADER,
   "First Module",
   coreSO_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(coreSO)
#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);
}

ZEND_FUNCTION(cs_get_map)
{
  /* my code
  */

.
.
.
}

ZEND_FUNCTION(cs_get_stats)
{
  /* my other code
  */

.
.
.
}

[/SNIP---------------------------------------------]

Like I said, I tried before with function names like this:

csGetMap
cdGetStats

It didnt work until I made them lower case.
(Note - I added the underscores to the names to aid
readability after I deleted the capital letters from the
function names)

Something to do with zend internals. Its probably documented
somewhere but I couldnt easily find it. Its just the sort of "gotcha"
that I thought would be useful in this forum.

I hope that saved someone some trouble.  ;)
spsuhas at yahoo dot com
22-Jun-2003 08:23
If you want to write extension for windows system, Take a look at this article



It works!
Suhas
Ed a PHP enthusiast from NYC
28-Apr-2003 05: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  ;-)
17-Apr-2003 06: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 07: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.
wish I didn't have to use PHP
12-Oct-2002 04:00
The example source has "#if COMPILE_DL_FIRST_MODULE", while the example compilation commands have "-DCOMPILE_DL=1".

Those constants should be the same for everything to work properly; i.e., I'd suggest using "-DCOMPILE_DL_FIRST_MODULE=1" in the compile command.

<PHP's Automatic Build SystemUsing Extensions>
 Last updated: Tue, 21 Dec 2004
show source | credits | sitemap | contact | advertising | mirror sites 
Copyright © 2001-2005 The PHP Group
All rights reserved.
This unofficial mirror is operated at: /
Last updated: Mon Mar 14 08:13:06 2005 Local time zone must be set--see zic manual page