编写自己的php扩展函数
php程序写的时间长了,自然对他所提供的功能了如指掌,他所提供的一大堆功能,真是觉得很好用,但有时候会发现php也缺少一些功能,自己总是会产生为php添加一些自定义的功能的想法。久而久之,终于今天憋不住了,开始动手研究如何添加。;下载一个php的源代码包,这里使用的是php 4.0.5版,解压后会看到php的根目录下会有README.EXT_SKEL这样一个文件,打开详细阅读了一下,发现了一个非常好用的工具,这个工具可以帮你构建一个空的php扩展,然后你向里面添加相应的代码就可以完成你自己的功能扩展了。下面我们就来介绍如何使用这个工具。;首先转移你的目录到php的目录下的ext目录,如果你只需要一个基本的扩展框架的话,执行下面的命令:./ext_skel --extname=module_namemodule_name是你自己可以选择的扩展模块的名字,例如我选择的my_module。执行工具后会自动在ext目录下建立你选择的module_name名字的目录,里面已经生成了相关的代码,这些代码中只需要调整config.m4文件中的三行注释就可以正常的编译带这个自定义扩展模块的php了。在php的根目录执行下列操作就可以得到。./buildconf./configure --enable-module_namemake;下面我来演示建立my_module扩展框架的全过程,为了更有效果,我们来完成一个php的扩展功能,在php中调用这个功能可以在web页面中显示hello world这个经典单词。在php目录下的ext目录中,执行下面的命令./ext_skel --extname=my_module得到反馈结果:Creating directory my_moduleCreating basic files: config.m4 Makefile.in .cvsignore my_module.c php_my_module.h tests/001.phpt my_module.php [done].;To use your new extension, you will have to execute the following steps:1. $ cd ..2. $ vi ext/my_module/config.m43. $ ./buildconf4. $ ./configure --[with|enable]-my_module5. $ make6. $ ./php -f ext/my_module/my_module.php7. $ vi ext/my_module/my_module.c8. $ make;Repeat steps 3-6 until you are satisfied with ext/my_module/config.m4 andstep 6 confirms that your module is compiled into PHP. Then, start writingcode and repeat the last two steps as often as necessary.;如果你能看懂上面的东西,那就照着去做。如果不是太明白的话,按照我下面的提示来做也可以。Cd my_module首先进入my_module目录vi config.m4使用文本编辑器打开config.m4文件,文件内容大致如下:dnl $Id$dnl config.m4 for extension my_modulednl don't forget to call PHP_EXTENSION(my_module);dnl Comments in this file start with the string 'dnl'.dnl Remove where necessary. This file will not workdnl without editing.;dnl If your extension references something external, use with:;dnl PHP_ARG_WITH(my_module, for my_module support,dnl Make sure that the comment is aligned:dnl [ --with-my_module;Include my_module support]);dnl Otherwise use enable:;dnl PHP_ARG_ENABLE(my_module, whether to enable my_module support,dnl Make sure that the comment is aligned:dnl [ --enable-my_module; Enable my_module support]);if test "$PHP_MY_MODULE" != "no"then;dnl If you will not be testing anything external, like existence of;dnl headers, libraries or functions in them, just uncomment the;dnl following line and you are ready to go.;dnl Write more examples of tests here...;PHP_EXTENSION(my_module, $ext_shared)Fi;根据你自己的选择将dnl PHP_ARG_WITH(my_module, for my_module support,dnl Make sure that the comment is aligned:dnl [ --with-my_module;Include my_module support])修改成PHP_ARG_WITH(my_module, for my_module support,Make sure that the comment is aligned:[ --with-my_module;Include my_module support])或者将dnl PHP_ARG_ENABLE(my_module, whether to enable my_module support,dnl Make sure that the comment is aligned:dnl [ --enable-my_module; Enable my_module support])修改成PHP_ARG_ENABLE(my_module, whether to enable my_module support,Make sure that the comment is aligned:[ --enable-my_module; Enable my_module support]);一般我会选择后者,然后保存退出。如果你对vi文本编辑器的操作有困难的话,请参考相应的说明文章,这里就不再详细描述了。Vi my_module.c将文件其中的下列代码进行修改/* Every user visible function must have an entry in my_module_functions[].*/function_entry my_module_functions[] = {;;;;PHP_FE(say_hello,;;;NULL) /*ß添加着一行代码*/;;;;PHP_FE(confirm_my_module_compiled,;;NULL) /* For testing, remove later. */;;;;{NULL, NULL, NULL};;/* Must be the last line in my_module_functions[] */};;在文件的最后添加下列代码PHP_FUNCTION(say_hello){;;;;zend_printf("hello worldn");}保存文件退出;vi php_my_module.h在文件中PHP_FUNCTION(confirm_my_module_compiled);一行前面添加下面的代码PHP_FUNCTION(say_hello);保存文件退出;退回到php的根目录下,执行下面的命令./buildconf./configure --enable-my_modulemake;如果一切顺利的话,我们现在已经将扩展模块my_module编译到php里面了。我们编写下面的代码进行测试<?;;;Say_hello();?>保存文件为say_hello.php在php的根目录下运行./php –q say_hello.php正常情况下会显示hello world表示我们的第一个扩展正常的运行了!;解释一下上面做的操作,ext_skel生成一些框下文件,我们需要修改以下文件my_module.c 扩展模块的主程序php_my_module.h扩展模块的头文件config.m4 配置文件;主程序中描述了php扩展模块的声明,模块中含有多少个函数,各个函数的作用,在phpinfo函数中显示什么内容,模块初始化做些什么,结束做些什么都会在这个文件里进行描述。我们在上面只是添加了一个函数say_hello,并且描述了say_hello函数的具体内容,调用zend_printf系统函数在php中打印字符串。;在对应的头文件中声明了say_hello这个函数,从而完成了我们预期的功能。下面我们会编写一个更复杂的扩展,创造一个带参数的php扩展函数,根据给入的参数,显示hello world, xxxx。Xxxx代表输入的字符串内容,例如我的名字yorgo。;Vi my_module.c修改最后的say_hello函数内容如下:PHP_FUNCTION(say_hello){;;;;zval **yourname;;;;;;if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &yourname) == FAILURE);;;;{;;;;WRONG_PARAM_COUNT;;;;;};;;;;zend_printf("hello world, %sn", Z_STRVAL_PP(yourname));}存盘退出。退回php的根目录,运行make修改say_hello.php为<?;;;Say_hello(“yorgo);?>保存退出后运行./php –q say_hello.php得出结果hello world, yorgo表示我们这次的修改也成功了,可以改变say_hello中的参数,看看动态的效果。这里主要解释上面修改的函数内容,由于say_hello函数需要有参数引入,所以在my_module.c中的say_hello函数主要在进行参数的处理,将php中引用say_hello时所填写的参数内容正确的传递到my_module.c中的say_hello处理函数中。为此,程序中添加了这么几行。zval **yourname;if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &yourname) == FAILURE){WRONG_PARAM_COUNT;}zend_printf("hello world, %sn", Z_STRVAL_PP(yourname));;代码解释如下:zval **yourname;初始化一个参数的指针ZEND_NUM_ARGS()得到传递过来得参数数量,并且判断如果不为1的时候表示有问题,报错。zend_get_parameters_ex(1, &yourname)将刚刚初始化的指针指向传递过来的参数,如果不成功则报错。Z_STRVAL_PP(yourname)处理指针指向的参数并获得实际存储的值。