##0x2 hello world!,你的第一个php扩展##

阅读前必看小贴士:

如果你不想在本教程上拷贝代码,你可以clone下这个仓库github,每一小节的代码对应着每一小节的分支,当阅读到该小节的时候,你可以切换到该小节的代码分支。

$ git clone git://github.com/kchodorow/rlyeh.git

比如当前小节的代码分支名是oop,你可以这样

$ git checkout -b oop origin/oop

本章的代码的分支是master,你可以直接

$ git clone git://github.com/kchodorow/rlyeh.git

而不用切换分支。


##正文开始##


我们可以在任何地方创建一个文件夹rlyeh

$ mkdir rlyeh
$ cd rlyeh

一个php扩展至少由下面的3个文件组成

  1. “config.m4”, which contains compilation instructions for PHP
  2. “php_extname.c”: source code
  3. “php_extname.h”: a header file

首先创建config.m4文件,不过这个真的很无聊,里面的内容差不多都是规定的,你知道有这个就可以了,我建议最好是在代码仓库里拷贝这些代码


dnl lines starting with "dnl" are comments

PHP_ARG_ENABLE(rlyeh, whether to enable Rlyeh extension, [  --enable-rlyeh   Enable Rlyeh extension])

if test "$PHP_RLYEH" != "no"; then

  dnl this defines the extension
  PHP_NEW_EXTENSION(rlyeh, php_rlyeh.c, $ext_shared)

  dnl this is boilerplate to make the extension work on OS X
  case $build_os in
  darwin1*.*.*)
    AC_MSG_CHECKING([whether to compile for recent osx architectures])
    CFLAGS="$CFLAGS -arch i386 -arch x86_64 -mmacosx-version-min=10.5"
    AC_MSG_RESULT([yes])
    ;;
  darwin*)
    AC_MSG_CHECKING([whether to compile for every osx architecture ever])
    CFLAGS="$CFLAGS -arch i386 -arch x86_64 -arch ppc -arch ppc64"
    AC_MSG_RESULT([yes])
    ;;
  esac
fi

再创建 php_rlyeh.c 文件

// include PHP API
#include <php.h>

// header file we'll create below
#include "php_rlyeh.h"

// define the function(s) we want to add
zend_function_entry rlyeh_functions[] = {
  PHP_FE(cthulhu, NULL)
  { NULL, NULL, NULL }
};

// "rlyeh_functions" refers to the struct defined above
// we'll be filling in more of this later: you can use this to specify
// globals, php.ini info, startup and teardown functions, etc.
zend_module_entry rlyeh_module_entry = {
  STANDARD_MODULE_HEADER,
  PHP_RLYEH_EXTNAME,
  rlyeh_functions,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  PHP_RLYEH_VERSION,
  STANDARD_MODULE_PROPERTIES
};

// install module
ZEND_GET_MODULE(rlyeh)

// actual non-template code!
PHP_FUNCTION(cthulhu) {
// php_printf is PHP's version of printf, it's essentially "echo" from C
php_printf("In his house at R'lyeh dead Cthulhu waits dreaming.\n");
}

上面的这个文件完全是一个模板式的文件,但是这个对我们是很重要的。但是你不知道不要紧,就像刚学java的时候,你不知道public static void main是什么意思一样。等后面我们再婉婉道来。

最后创建php_rlyeh.h文件,

#define PHP_RLYEH_EXTNAME "rlyeh"
#define PHP_RLYEH_VERSION "0.01"

PHP_FUNCTION(cthulhu);

你可以修改版本号,随你怎么写,使用

$ php --ri rlyeh

可以查看扩展模块的信息。(当然前提是这个模块已经安装)

到现在所有的准备工作都做完了哈。要开始编译安装php的扩展了:

$ echo $PATH
$PHPDIR/install-debug-zts/bin:/usr/local/bin:/usr/bin
$ phpize
Configuring for:
PHP Api Version: 20090626
Zend Module Api No:  20090626
Zend Extension Api No:   220090626
$
$ ./configure
# lots of checks...
$
$ make
# compile...

Build complete.
Don't forget to run 'make test'.

$ make install
$
Installing shared extensions: $PHPDIR/install-debug-zts/lib/php/extensions/debug-zts-20090626/

现在把扩展添加进php.ini文件中,一般来说php.ini的位置在($PHPDIR/install-debug-zts/lib/php.ini),如果没有这个文件可以从php的源码的根目录拷贝一个过去。
添加这行:

extension=rlyeh.so

现在你就可以使用你为php写的扩展函数,就和php的其他内置函数一样,不用导入文件拿起来就是用:

$ php -r 'cthulhu();'
In his house at R'lyeh dead Cthulhu waits dreaming.

恭喜你的一个扩展文件已经开始工作了。