首先,我们需要PHP源码包,如果没有就下一个吧,反正很近,就 http://www.php.net了。:D
Linux/BSD下的步骤
[yingyuan@research src]$ pwd /home/yingyuan/data1/src [yingyuan@research src]$ ls php-4.3.4.tar.gz [yingyuan@research src]$ tar zxvf php-4.3.4.tar.gz ... [yingyuan@research src]$ cd php-4.3.4
现在我们到了PHP源代码根目录,下文简称为$PHP_SRC_HOME。
仔细看看,这里有这么几个子目录是需要注意的:main, TSRM, Zend。这些子目录包含了编译扩展模块必要的头文件。
[yingyuan@research php-4.3.4]$ cd ext [yingyuan@research ext]$ ls ... ext_skel ext_skel_win32.php ...
这个目录有很多子目录,每个子目录都是PHP的一个扩展模块。此外还有两个文件:ext_skel是一个shell脚本,运行它能生成PHP扩展模块的框架;ext_skel_win32.php,用来生成Windows下的PHP扩展模块框架。偶心中窃喜,ext_skel_win32.php,哈,开发Windows下的PHP扩展模块变得如此Easy。话虽如此,可是别忘了装CygWin(http://www.cygwin.com/)这个胖的可爱的小助理。像我这样心疼时间的人当然不会装了,所以通常我是在Linux/BSD下用ext_skel生成框架,然后拷贝到Windows下用的。
诸位,我们开始干活了。先看看我们在哪里:
[yingyuan@research ext]$ pwd /home/yingyuan/data1/src/php-4.3.4/ext
假设我们要写一个很恢宏的PHP扩展模块,模块名叫 myext,则运行如下命令:
[yingyuan@research ext]$ ./ext_skel --extname=myext Creating directory myext Creating basic files: config.m4 .cvsignore myext.c php_myext.h CREDITS EXPERIMENTAL tests/001.phpt myext.php [done]. 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. $ ./php -f ext/myext/myext.php 7. $ vi ext/myext/myext.c 8. $ make Repeat steps 3-6 until you are satisfied with ext/myext/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_skel替我们生成了模块myext的骨架:目录myext, 目录myext下的文件config.m4、php_myext.h、myext.c、myext.php。至于其他文件我就懒得考虑了。
根据提示,我们做如下操作。
[yingyuan@research ext]$ cd .. [yingyuan@research php-4.3.4]$ vi ext/myext/config.m4
关于m4文件的撰写说明,这里没空共享给各位了,感兴趣可以上 http://www.gnu.org/software/m4/manual/index.html 瞧瞧。
这里有必要说明一下:
PHP编译的时候要激活某个扩展模块,有两种方式,--with-xxxx和--enable-xxxx。差别在于前者可以引用外部相关文件,比如--with-mysql=/usr/local/mysql等等,而后者不能。这要根据你的需要,比如你要写一个xml parser扩展,想在你的扩展代码中引用外部系统的libxml,那么为了保证你的代码总是能成功找到必要的libxml文件,就可以用--with-xxxx方式,让用户在编译的时候指定libxml文件位置。
我们这里用--enable-xxxx吧,因为我们的myext确实没什么好引用的。
找到这么几行:
dnl PHP_ARG_ENABLE(myext, whether to enable myext support, dnl Make sure that the comment is aligned: dnl [ --enable-myext Enable myext support]) if test "$PHP_MYEXT" != "no"; then dnl Write more examples of tests here... ...
改成:
PHP_ARG_ENABLE(myext, whether to enable myext support, [ --enable-myext Enable myext support]) if test "$PHP_MYEXT" == "yes"; then dnl Write more examples of tests here... ...
首先需要告诉PHP自动编译系统不要对我们的扩展模块视而不见,然后还需要在用户明确要求enable我们的扩展模块时才编译。这就是以上修改的原因。
接着往下走:
[yingyuan@research php-4.3.4]$ ./buildconf You should not run buildconf in a release package. use buildconf --force to override this check.
系统抱怨说发行版本不能运行 buildconf,嘿嘿,我们强制运行:
[yingyuan@research php-4.3.4]$ ./buildconf --force [yingyuan@research php-4.3.4]$ ./configure --help | grep myext --enable-myext Enable myext support
从这个输出可以看到我们的扩展模块已经可用。
[yingyuan@research php-4.3.4]$ ./configure --enable-myext ... [yingyuan@research php-4.3.4]$ make ... [yingyuan@research php-4.3.4]$ ./sapi/cli/php -f ext/myext/myext.php Functions available in the test extension: confirm_myext_compiled Congratulations! You have successfully modified ext/myext/config.m4. Module myext is now compiled into PHP.
至此我们的demo函数已经奏效,接下来听你们提问了:
Q1:我一定要make整个PHP代码包才可以make我的扩展模块吗?
A1:不用。你甚至不用修改config.m4文件。方法是手工编译扩展模块:
切换到目录$PHP_SRC_HOME/ext
cc -fpic -DCOMPILE_DL=1 -DCOMPILE_DL_module_name -I/usr/local/include -I. -I.. -I../Zend -I../main -I../TSRM -c -o
cc -shared -L/usr/local/lib -rdynamic -o
本例中,
[yingyuan@research php-4.3.4]$ cd ext [yingyuan@research ext]$ cc -fpic -DCOMPILE_DL=1 -DCOMPILE_DL_MYEXT -I/usr/local/include / -I. -I.. -I../Zend -I../main -I../TSRM -c -o myext/myext.o myext/myext.c [yingyuan@research ext]$ cc -shared -L/usr/local/lib -rdynamic -o myext/myext.so myext/myext.o
Q2:怎样为我的扩展模块生成GUN AutoMake兼容的自动编译文件
A2:利用$PHP_SRC_HOME/scrīpts/phpize。其实$PHP_SRC_HOME/scrīpts/下面还有别的有意思的东西。:D
Q3:怎样用C++写PHP扩展模块
A3:这涉及到C和C++的名称转换问题,需要对C定义的头文件用extern "C"包围起来,本文不提供更详细的信息。
Windows下的步骤
我们需要前面所说的PHP源代码包,还需要php4ts.lib。后者可以在PHP的Windows安装包中找到。这里我们谈谈用VC 6如何开发PHP扩展模块。不要有恐惧心理,微软让事情变得更简单而不是更复杂。
我们新建一个Win32 Dylamic-Link Library项目myext,选择Empty Project。然后把ext_skel生成的两个文件php_myext.h、myext.c添加到项目中,做如下设定:
打开菜单项 Build >> Set Active Configuration...,这里有两个项可供选择:Win32 Release和Win32 Debug,我们这里选择Win32 Release。
打开菜单项 Tools >> Options,选择Directories属性页.在这里可以对头文件和库文件的搜索路径进行设置.
在Show directories for 下拉列表中选择Library files, 把php4ts.lib所在的目录添加进去.比如C:/PHP/PHP-4.3.11.
在Show directories for 下拉列表中选择Include files,把PHP头文件所在的路径加上,比如:
C:/PHP/PHP-4.3.4
C:/PHP/PHP-4.3.4/main
C:/PHP/PHP-4.3.4/TSRM
C:/PHP/PHP-4.3.4/Zend
打开菜单项 Project >> Settings...,选择C/C++属性页。
在Category下拉列表中选择Code Generation,在Use run-time library下拉列表中选择Multithreaded DLL(对应于Win32 Release版本)或者Debug Multithreaded DLL(对应于Win32 Debug版本)。
在Category下拉列表中选择Preprocessor,在Preprocessor defines里添加 ZEND_DEBUG=0,COMPILE_DL_SIPLOOKUP,ZTS=1,ZEND_WIN32,PHP_WIN32。如果你在调试你的工程,可把ZEND_DEBUG设置为1.这里也可以在Additional include directories设置搜索头文件,不过因为我们已经在以上的步骤设置了,就没有必要了。最后我们在Project Options中添加选项 /Tc,这告诉编译器把我们的源文件当C程序处理。
在菜单项 Project >> Settings...中,选择Link属性页。
在Object/library modules中把php4ts.lib添加进去。
然后就可以进行Build,生成我们的DLL文件。如果有错误不用着急,相信自己,相信Google。^_^
几点建议
PHP手册是开发扩展模块最好的教材,如果有心于斯就一定要看看,这个不能偷懒了;
PHP扩展模块开发网站 http://pecl.php.net 可以去看看;
如果不知道该如何着手,比如不知道怎样创建Resource,或者从函数中返回值,最快的方式就是翻翻$PHP_SRC_HOME/ext下的扩展模块源代码,很多东西都可以参考的。