Categories
How-To WebApps

How to Make Your Own PHP Extension… Quick and Dirty

This is a cheat sheet on how to extend PHP. I’m learning how to fix bugs in C within the PHP source code right now using what’s google-able, the #php chat room in irc.freenode.net and “Extending and Embedding PHP” by Sara Goleman.

Preliminaries: make sure you have the right tools for building php from source. Right now these tools are:

  • autoconf: 2.13
  • automake: 1.4+
  • libtool: 1.4.x+ (except 1.4.2)
  • bison: 1.28, 1.35, 1.75, 2.0 or higher
  • flex: 2.5.4 (not higher)
  • re2c: 0.9.11+ (0.12.0+ for HEAD)
  • Get the latest php stable version. as of this blog posting it’s php-5.2.6
  • unpack the file using something like bunzip2 -c < php-5.2.6.tar.bz2 | tar xvf -
  • ./configure –prefix=/usr/local –enable-debug (I’m really old school and like to put my stuff in /usr/local . YMMV.)
  • make ; make install

If that worked now we’re ready to make a module. Feel free to substitute barce or BARCE in the code below with whatever you want the module name to be.

  • cd ext (if you type ls you’ll see the extensions that come with php.)
  • mkdir barce (I’m a narcissistic, buddhist, nihilist.)
  • create a config.m4 file with this code:
PHP_ARG_ENABLE(barce,
        [Whether to enable the "barce" extension],
        [  --enable-barce       Enable "barce" extension support])

if test $PHP_BARCE != "no"; then
        PHP_SUBST(BARCE_SHARED_LIBADD)
        PHP_NEW_EXTENSION(barce, barce.c, $ext_shared)
fi
  • then create a php_barce.h file:
#ifndef PHP_BARCE_H
/* Prevent double inclusion */
#define PHP_BARCE_H

/* Define extension properties */
#define PHP_BARCE_EXTNAME "barce"
#define PHP_BARCE_EXTVER "1.0"

/* Import configure options
 * when building outside of the 
 * PHP source tree */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

/* Include PHP standard Header */
#include "php.h"
/*
 * define the entry point symbole
 * Zend will use when loading this module
 */
extern zend_module_entry barce_module_entry;
#define phpext_barce_ptr &barce_module_entry

#endif /* PHP_BARCE_H */

  • create a barce.c file with your functions that you are creating for PHP
#include "php_barce.h"

PHP_FUNCTION(barce_thinks_youre_cool)
{
        char *name;
        int name_len;

        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", 
                &name, &name_len) == FAILURE)
        {
                RETURN_NULL();
        }

        php_printf("Barce thinks you're cool, ");
        PHPWRITE(name, name_len);
        php_printf("!\n");
}


static function_entry php_barce_functions[] = {
        PHP_FE(barce_thinks_youre_cool, NULL)
        { NULL, NULL, NULL }
};

zend_module_entry barce_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
        STANDARD_MODULE_HEADER,
#endif
        PHP_BARCE_EXTNAME,
        php_barce_functions, /* Functions */
        NULL, /* MINIT */
        NULL, /* MSHUTDOWN */
        NULL, /* RINIT */
        NULL, /* RSHUTDOWN */
        NULL, /* MINFO */
#if ZEND_MODULE_API_NO >= 20010901
        PHP_BARCE_EXTVER,
#endif
        STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_BARCE
ZEND_GET_MODULE(barce)
#endif

Now let’s build this puppy.

  • phpize
  • ./configure –enable-barce
  • make
  • there should now be a modules directory. copy it to /usr/local/lib/php/modules/ .
  • edit php.ini and add two lines:
    • extension_dir = “/usr/local/lib/php/modules”
    • extension = “barce.so”

Let’s test and see if it worked:

php -r “barce_thinks_youre_cool(‘Put your name here’);”