编写PHP的C扩展,有三种方式:

1、External Modules:外部模块,也就是编译成共享库,用dl()函数动态加载

好处:

(1)不需要重新编译PHP
(2)PHP体积小,因为不需要编译进PHP

缺点:

(1)每次*.php脚本执行都需要用dl()去加载,效率较低
(2)每次都要调用dl()

2、Built-in Modules:编译进PHP

好处:

(1)不需要动态加载,模块在php脚本里面可以直接使用
(2)不需要将模块编译成.so共享库,因为直接编译进PHP

缺点:

(1)对模块的改变都需要重新编译PHP
(2)因为编译进PHP,所以PHP二进制文件较大,而且多占点内存

3、The Zend Engine:Zend核心里实现(略……有兴趣的话可以看Zend API)

Note:推荐用第2种方式,直接编译进PHP,但是在下面示例里,我们编译成外部模块,因为,外部模块不需要重新编译PHP,所以在测试阶段先编译成共享库,测试完后再用第2种方式重新编译进PHP。

第一步

下载PHP的源代码,现在最新的php-5.6.13

wget http://cn2.php.net/distributions/php-5.6.13.tar.gz
tar -zxvf php-5.6.13.tar.gz

解压后进入php-5.6.13/ext目录。输入 ./ext_skel –extname=myExt,myExt就是扩展的名称,执行后生成myExt目录。

cd php-5.6.13/ext
./ext_skel --extname=myExt

运行之后,显示如下

To use your new extension, you will have to execute the following steps:
1.  $ cd ..
2.  $ vi ext/myExt/config.m4
3.  $ ./buildconf
4.  $ ./configure --[with|enable]-myExt
5.  $ make
6.  $ ./sapi/cli/php -f ext/myExt/myExt.php
7.  $ vi ext/myExt/myExt.c
8.  $ make

第二步

修改 config.m4 config.m4是AutoConf工具的配置文件,用来修改各种编译选项。

dnl PHP_ARG_WITH(myExt, for myExt support,
dnl Make sure that the comment is aligned:
dnl [  --with-myExt Include myExt support])

修改为

PHP_ARG_WITH(myExt, for myExt support,
[  --with-myExt Include myExt support])

修改php_myExt.h,在最下方增加一行 PHP_FUNCTION(myExt_helloworld); 表示声明了一个myExt_helloworld的扩展函数。

第三步

修改myExt.c,这个是扩展函数的实现部分。

const zend_function_entry myExt_functions[] = {
    PHP_FE(confirm_myExt_compiled,  NULL) 
    PHP_FE(myExt_helloworld,  NULL)
    PHP_FE_END
};

这的代码是将函数指针注册到Zend引擎,增加一行PHP_FE(myExt_helloworld,  NULL)

第四步

修改myExt.c,在末尾加myExt_helloworld的执行代码。

PHP_FUNCTION(myExt_helloworld)
{
    char *arg = NULL;
    int arg_len, len;
    char *strg;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
        return;
    }
    php_printf("Hello World!\n");
    RETURN_TRUE;
}

zend_parse_parameters是用来接受PHP传入的参数,RETURN_XXX宏是用来返回给PHP数据。

在myExt目录下依次执行phpize、./configure 、make、make install。然后修改php.ini加入extension=myExt.so

重启php-fpm,通过phpinfo看到我们编写的myExt扩展已经加载

执行php -r "myExt_helloworld('test');",输出hello world!