这篇文章将会系统的介绍如何开发自己的PHP扩展, 也许你会说,网上这样的文章已经很多了,为什么还要写? 呵呵,我当然不会只是简单的重复。 这篇文章将会涉及到很多的高级技术,比如在自己的扩展中使用资源,开发一个类给脚本使用,在PHP中使用C++的对象等等,另外这篇文章还会穿插很多Zend引擎和PHP内核的知识,比如变量的实现,资源的实现,PHP4和PHP5对类的不同实现等等
首先,我们要有个认识,那就是在php中的类和函数,以至于变量,在本质上都是C实现的。 你所编写的脚本,最终都会被转换成C代码来执行。 这个和我在以前文章中(深入理解PHP原理之Opcodes)介绍的opcode并不冲突, 因为Zend虚拟机的指令最终还是要翻译成C代码来执行。
开发者也就可以使用C/C++来写一些PHP的函数,类。从而扩展PHP, 那么,为什么要扩展PHP呢? 很多同学只是盲目的去扩展,认为扩展PHP是一个很有“意义”的事(许三多语气),而我认为,扩展PHP只是在特定的情况才有必要,最主要的俩个原因是:
其实第二个理由,已经是很充足了,但是用扩展来实现你的逻辑,并不是那么简单的事情:
首先如果你是使用PHP来实现你的逻辑,那么你不需要考虑资源管理,Zend会替你完成。其次你也不需要担心, 代码的一个简单的错误,就会导致PHP core dump。
而如果你用C来编写PHP的扩展,那么你就要自己考虑这些事情,自己管理资源的分配,使用,释放。 你也要学会适应segmentation fault
。 我要提醒你的是, 因为PHP是一个长时间运行的模块(因为Apache是一个长时间运行的Web服务器), 所以,你千万要防止资源泄露, 我就遇到过一个简单的字符串泄露, 在一段时间以后,Apache占用的内存超过了1个G。
接下来,总结一下用C/C++扩展PHP的优缺点:
优点:
而缺点也是显而易见的:
恩,现在你看到了, 用C/C++实现PHP扩展的优点和缺点了,那么你就可以自己权衡你的逻辑,是要用那种方式实现了。呵呵
如果你熟悉C,那么编写一个PHP扩展,并不是什么非常难的事情。 PHP本身就提供了一个框架,来简化你的开发。
最简单的方式来开始一个PHP扩展的开发,是使用PHP提供的扩展框架wizard ext_skel, 它会生成一个PHP扩展所必须的最基本的代码, 要使用它,首先你要下载PHP的源码,或者开发包, 进入PHP源码的ext目录, 就会发现这个工具。比如我下载了PHP源码php5.2-SRC到/home/xinchen/,那么这个工具的路径就在: /home/xinchen/php5.2-SRC/ext下。
这个工具的使用方式也很简单, 比如我们要创建一个名叫example的扩展,那么:
$ cd ~/php5.2-SRC/ext $ ./ext_skel --extname=example Creating directory example Creating basic files: config.m4 config.w32 .cvsignore example.c php_example.h CREDITS EXPERIMENTAL tests/001.phpt example.php [done]. To use your new extension, you will have to execute the following steps: 1. $ cd .. 2. $ vi ext/example/config.m4 3. $ ./buildconf 4. $ ./configure --[with|enable]-example 5. $ make 6. $ ./php -f ext/example/example.php 7. $ vi ext/example/example.c 8. $ make Repeat steps 3-6 until you are satisfied with ext/example/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.
这样,就在ext目录下生成了一个名为example的目录,并在这个目录下生成了所有的要完成一个PHP扩展所必须的文件和代码(事实上,这个目录下的文件,已经可以生成一个PHP的标准扩展了,只不过这个扩展不完成任何功能,就好像我们使用Visual Studio的Wizard生成的一个空的MFC框架一样)。接下来,我们要做的就是不停的重复最后俩个步骤,从而实现我们的功能。
在这个目录下,我们要尤其关注的是example.c这个文件,这个文件是我们扩展的主要文件,也就是说,如果我们要充实我们的扩展,那么就需要在这个文件中进行工作。 在后面的内容中,我会消息介绍这个文件中包含的各个字段,结构的含义,现在我们就只是简单的掠过他。
第二个要特别注意的文件就是config.m4,如果读者你有过在Unix/Linux下的编程经历,那么你或许听过autoconf和m4, m4是一个宏解释工具,它会把输入文件中的宏展开到输出文件。所以这个config.m4是PHP扩展框架所必须的,也是关键的一个文件,用来生成我们扩展的makefile。
在config.m4中,有一行:
PHP_ARG_ENABLE(example, whether to enable example support, [ --enable-example Enable example support])
在m4中,dnl表示注释, 这段指令创建了一个configure时的参数“enable-example”, 第二个参数会显示在当configure处理到这个模块的configure文件的时候。第三个参数,会在用户输入./configurehelp的时候,作为一个可选的选项被显示。
另外还有一段:
PHP_ARG_WITH(example, for example support, [ --with-example Include example support])
严格来说,上面的俩段没有太大的区别,只不过with是说明了,要启用这个模块,必须要的先决条件,也就是说这个模块依赖于某些其他模块。
就好像:
./configure --with-apxs=/usr/local/apache/bin/apxs --enable-example
PHP的扩展框架构建系统,支持全套的.m4语法,当然还支持用户自定义的宏, 下面我介绍一些常见的,由PHP扩展框架构建系统定义的宏:
PHP_CHECK_LIBRARY(library, func [, found [, not-found [, extra-libs]]])
在库library中查找func是否存在,如果存在则这个宏会被展开成found,否则not-found;
PHP_DEFINE(what, [value])
这个就是对AC_DEFUN简单包装,最终会被展开成:
#define what value
PHP_REQURE_CXX
如果你的扩展是使用C++编写,那么你就必须使用这个宏,来告诉编译器使用C++编译器。这个宏会被展开成:
AC_PROG_CXX
AC_PROG_CXXCPP
更多的由PHP扩展框架构建系统提供的宏,你可以到acinclude.m4中查看。
还有一些其他的有ext_skel创建的文件:
CREDITES 这个文件没什么太大的作用,只是用来在发布你的扩展的时候附加一些其他信息 ,比如作者啊,等等。
EXPERIMENTAL 这个文件只是标志说,这个扩展是实验性的,所以你可以不用管它
example.php 这个文件是用来简单测试你的扩展的
php_example.h 这个是我们扩展的头文件
tests/001.phpt 这个也是个测试文件, 不过使用的是单元测试, 阶段测试, 具体内容,你打开一看便知 ;)
下一次我讲介绍一些要开发扩展,最好要先了解的知识,比如变量的内部表示,copy-on-write , change-on-write机制, 函数的内部表示==。 当然,这其中有些知识是我以前的文章已经涉及过的:
PHP的函数(Introspecting PHP Function)
恩,这个文章要持续开发。
顶,学习了
很难啃,舔一舔也好
部分内容似乎在哪见过,不过写的不错,支持博主。
恩,网上有不少介绍扩展PHP的文章,;) “也许你会说,网上这样的文章已经很多了,为什么还要写?”
网上有很多类似文章,但介绍的要么过于简单,要么过于艰深,希望博主再接在励。
恩,有些内容我不会完全归类到这个系列下面,但是确实和这个系列相关的。最后我会把相关的东西整理起来,所以你可以看看我其他的文章,不一定等我归类到这个系列后再看,;)
强烈支持楼主,非常好的文章!
希望楼主继续写关于扩展方面的文章.加油!
强烈支持博主,你在linux下的c-php很有技术含量。希望能与博主结识为朋友!
@lixiphp 握手~,