操作系统:Mac OS / Linux
在开始之前,应该先下载 PHP 源码,可到 http://php.net/get/php-5.6.12.tar.bz2/from/a/mirror 下载,这里选择的是中国的。下载之后解压,存放到自己喜欢的任何一个工作目录中,比如我这里是放在 Mac 桌面。另外,系统中需要安装有 C 的编译环境,另外还有 make 和 autoconf。因此,在 linux 中可以直接通过 sudo apt-get install gcc make autoconf来同时安装这三样东西。而在Mac中,只需要安装个 autoconf 就可以了,其他的系统自带, 可利用命令 sudo brew install autoconf 安装。
得到PHP源码之后,cd 进入该文件夹,里面有个 etx 文件夹,如下图所示:
cd 进入该文件夹,ls 命令可看到etx_skel 文件,这个文件可以用来生成扩展模块,执行 ./ext_skel --extname=test 即可在该目录下创建一个叫 test 的扩展文件,cd test 进入后利用 ls 命令可看到一系列文件,如下图所示,其中 config.m4 是相关的扩展配置文件:
命令行中利用 sudo vim config.m4 打开,找到如下部分,去掉前面的 dnl 后保存, 结果如下所示(dnl 是在该文件中用于注释的):
接下来,直接在命令行中敲打 phpize,它会根据刚刚修改的 config.m4 生成一个 configure 脚本,之后执行该脚本,它便会继续生成一个 Makefile 文件, 具体如下:
有了 Makefile 文件,我们便能通过 make 和 sudo make install 进行 C 源文件的编译。之后我们可以利用php -i | grep php.ini 找到 php.ini 这个配置文件的路径,在最后加上extension=test.so,表示开启 test 扩展。开启之后利用命令 php -m 检查一下,你会发现在列出来的所有 module 中存在一个叫 test 扩展。
继续之前的 sudo make install 编译之后,在 test 文件夹中我们可以看到 一个 php_test.h 文件和一个 test.c 文件。我们在写 C 的时候,可以在不同的文件中声明和定义一个函数,关键是需要在定义该函数的文件中 include 声明该函数的文件。而在PHP扩展中也一样,我们是在 PHP_test.h 中声明我们扩展的函数而在 test.c 中定义该函数。当然,php_test.h 和 test.c 这两个文件的命名是根据我们刚刚创建的扩展模块 test 命名的。
假设我们这里要实现一个函数的扩展,假设该函数名是 hello_world, 我们可以直接在 php_test.h 文件中利用如下语句声明该函数,PHP_FUNCTION 就类似 C 中的一个宏扩展。
<span style="font-size:14px;">PHP_FUNCTION(echo_hello_world);</span>
<span style="font-size:14px;">PHP_FUNCTION(hello_world) { long a; long b; char *c; int c_len; // <span style="font-family: Arial, Helvetica, sans-serif;">zend_parse_parameters 是 </span><span style="font-family: Arial, Helvetica, sans-serif;">PHP 其中的一个API, 用于从PHP中获取对应的参数</span> if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lls", &a, &b, &c, &c_len) == FAILURE){ return ; } char *str; int len = spprintf(&str, 0, "%s: %d\n", c, a*b); RETURN_STRINGL(str, len, 0); // PHP提供的返回类型 }</span>
<span style="font-size:14px;">const zend_function_entry test_functions[] = { PHP_FE(hello_world, NULL) /* For testing, remove later. */ PHP_FE_END /* Must be the last line in test_functions[] */ };</span>
首先我们先利用 php --rf "hello_world" 查看该函数是否存在,在 test 文件夹中输入该命令后出现类似如下的结果,表示对应的函数存在:(这里我查看的是echo_hello_world函数)
写个小php脚本测试,脚本简单如下所示:
<span style="font-size:14px;"><?php echo hello_world(100, 345, "hello world:100*345=");</span>