查阅了很多文献,花了一天多的时间终于总结出来了。了解了大体上的流程。
背景
--
做拓展主要是为了增加功能和提高性能,有三种方式
a.作为可以加载的模块,效率不会太高,移植方便。
b.静态的建入PHP内核,效率高,但目标主机需要重新安装PHP。
c.采用zend的api引擎,使用很少。
下文采用第一个方式实现
-----------
1.在目标机器上安装了LAMP,并安装php5-dev
2.下载PHP源码,执行以下步骤:
2.1 进入./php-5.2.9/ext,执行
$sudo ./ext_skel --extname=test
//这其实指定了要扩展的模块的名字,生成了一个test的文件夹。还有--proto=myfunctions.def参数用于定义函数。
Creating directory test
Creating basic files: config.m4 config.w32 .cvsignore test.c php_test.h CREDITS EXPERIMENTAL tests/001.phpt test.php [done].
To use your new extension, you will have to execute the following steps:
1. $ cd ..
2. $ vi ext/test/config.m4
3. $ ./buildconf
4. $ ./configure --[with|enable]-test
5. $ make
6. $ ./php -f ext/test/test.php
7. $ vi ext/test/test.c
8. $ make
Repeat steps 3-6 until you are satisfied with ext/test/config.m4 and
step 6 confirms that your module is compiled into PHP. Then, start writing
code and repeat the last two steps as often as necessary.
2.2 $sudo vim config.m4
去掉16,18行的注释,dnl
PHP_ARG_ENABLE(test, whether to enable test support,
dnl Make sure that the comment is aligned:
[ --enable-test Enable test support])
2.3 $sudo vim php_test.h
加入函数的声明
PHP_FUNCTION(confirm_hello_compiled); /* For testing, remove later. */
PHP_FUNCTION(test_add);
2.4 $sudo vim test.c
PHP_FE(confirm_test_compiled, NULL) /* For testing, remove later. */
PHP_FE(test_add, NULL) /* For testing, remove later. */
{NULL, NULL, NULL}
然后在 test.c 的最末尾书写test_add函数的内容:
PHP_FUNCTION(test_add)
{
long int a, b;
long int result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &a, &b) == FAILURE) {
return;
}
result = test_add(a, b);
RETURN_LONG(result);
}
2.5 编译
phpize
./configure
make
make install
MORE
---------------------------
1.上面的config.m4中的16,18行,其实是开启了编译选项--enable-test,这是因为没有加入相关的第三方c库。
--with-extension而要加入c库的扩展路径,
这个可以通过./configure -help|grep test来检查编译选项是否加入。
2.文件中的test.php用于检查是否编译并加入了PHP。
3.同PHP解决数组问题一样,这里涉及了变量传入问题。
在test.c中将会看到,
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &a, &b) == FAILURE) {
return;
}
//zend_parse_parameters函数第一个参数为变量的个数
//第二个是数据类型
l<>long
d<>double
s<>char *,int
b<>zend_tool
a,a,o,O,z<>zval *
//之后是变量的地址
4.从PHP返回值
RETURN_LONG(1)
RETURN_BOOL(B)
RETURN_DOUBLE(L)
RETURN_STRING(S,DUP)//DUP AS 1 OR 0
RETURN_STRINGL(S,1,DUP)
RETURN_TRUE()
RETURN_RESOUCE()