此篇文章准备分2个部分来讲述: 第一部分主要详细讲述一下怎么构建一个完成的C++应用扩展模块; 第二部分主要讲述在PHP及Zend框架下怎么使用Zend API和C++语言来实现自己所要的功能以及项目的开发; 此篇文章所运用的环境在Linux 2.4.21-4.ELsmp(Red Hat Linux 3.2.3-20),Apache/2.2.8,gcc version 3.2.3 20030502,PHP 5.2.5 (cli),Zend Engine v2.2.0下进行。 一、前言
二、为什么要用C++开发PHP
三、书写config文件config.m4[5 ] 或config.w32[6 ] 文件是编译基础中最核心的文件,这个文件主要是用autoconf[7 ] 来产生configure[8 ] 配置文件,继而自动生成大家所熟悉的Makefile文件,以Linux系统为例:你可以自己书写config.m4文件,也可以由Shell脚本 ext_skel[9 ] 来生成样板: [cnangel@localhost ~]$wget http://docs.php.net/get/php-5.2.5.tar.bz2/from/cn.php.net/mirror [cnangel@localhost ~]$tar -jxf php-5.2.5.tar.bz2 [cnangel@localhost ~]$cd php-5.2.6/ext [cnangel@localhost ext]./ext_skel --extname=extern_name接着你会发现在ext目录下多了一个叫extern_name的目录。进入该目录,会发现目录下有几个文件: [cnangel@localhost ext_name]$ls -l 总计 32 -rw-r--r-- 1 cnangel cnangel 2103 06-29 19:00 config.m4 -rw-r--r-- 1 cnangel cnangel 310 06-29 19:00 config.w32 -rw-r--r-- 1 cnangel cnangel 8 06-29 19:00 CREDITS -rw-r--r-- 1 cnangel cnangel 0 06-29 19:00 EXPERIMENTAL -rw-r--r-- 1 cnangel cnangel 5305 06-29 19:00 ext_name.c -rw-r--r-- 1 cnangel cnangel 508 06-29 19:00 ext_name.php -rw-r--r-- 1 cnangel cnangel 2766 06-29 19:00 php_ext_name.h drwxr-xr-x 2 cnangel cnangel 4096 06-29 19:00 tests然后可以根据提示来修改config.m4文件,这里有几个重要的宏命令如下:
需要注意的是,在config.m4里面可以使用类似的Makefile语法,片段如下: PHP_REQUIRE_CXX() INCLUDES="$INCLUDES `mysql_config --cflags`" PHP_ADD_LIBRARY(stdc++, "", EXTRA_LDFLAGS) EXTRA_LDFLAGS="$EXTRA_LDFLAGS `mysql_config --libs` -lmemcached" AC_CHECK_HEADERS([mysql/mysql.h]) CPPFILE="ext_name.cpp antiForbitWord.cpp antiBaseDict.cpp Trie.cpp Logger.cpp antiEncodeConverter.cpp strnormalize.cpp" PHP_NEW_EXTENSION(ext_name, $CPPFILE, $ext_shared) 四、书写.h文件这里指修改php_ext_name.h这个头文件。由于TSRM.h这个文件所包含的函数和类都是用纯C语言写的,故应该使用extern来说明如下: extern "C" { #ifdef ZTS #include "TSRM.h" #endif }如果该php_ext_name.h头文件或者ext_name.cpp文件用到了C++语言中的一些容器或者一些函数,则需要在头文件中包含相应的c++库的头文件,否则会出现找不到相应的C++函数错误。 五、书写.cpp文件这里指修改ext_name.cpp这个cpp文件。由于config.h、php.h、php_ini.h和ext/standard/info.h中包含的函数和类如TSRM.h一样,都是用纯C语言写的,所以也需要用extern说明如下: extern "C" { #ifdef HAVE_CONFIG_H #include "config.h" #endif#include "php.h" #include "php_ini.h" #include "ext/standard/info.h" }而 #include "php_ext_name.h" 这句则已经不需要包含在extern "C"内,另外,ZEND_GET_MODULE这个宏命令也是需要特别申明如下: #ifdef COMPILE_DL_EXT_NAME BEGIN_EXTERN_C() ZEND_GET_MODULE(ext_name) END_EXTERN_C() #endif总之,把一些C写的库或轰用兼容的方式给解决。 六、初步执行这里需要用到一个命令:phpize[10 ] ,命令如下:[cnangel@localhost ext_name]$phpize [cnangel@localhost ext_name]$./configure [cnangel@localhost ext_name]$make注意:可以使用用phpize生成configure执行文件后,可以使用./configure --help查看帮助信息,修改config.m4文件可以修改configure的帮助信息。每次修改了config.m4文件,需要使用清除临时文件 命令phpize --clean来完成消除configure。 七、初步应用怎么应用到php上,把刚才的扩展模块当作一个普通的php函数调用呢?简单的应用直接使用命令:[cnangel@localhost ext_name]$sudo make install如果有多个php版本,则寻找扩展库目录显得没有那么好找了,比如,你的php执行文件的路径在/usr/local/php/bin/目录下,想知道php扩展模块所在的目录的话,那么执行(PHP5.0以上): [cnangel@localhost ext_name]$/usr/local/php/bin/php-config | grep extension-dir | sed 's/.*/[/(.*/)]//1/'`PHP5.0以下执行: [cnangel@localhost ext_name]$/usr/local/php/bin/php-config --extension-dir这样你可以发现你的扩展库的路径: /usr/local/php/lib/php/extensions/no-debug-non-zts-20060613当然,你可以修改php.ini,找到php安装的配置文件,修改extension_dir的值为你想要的一个路径另外,需要将你的扩展写入php.ini,像这样: extension=ext_name.so 最后,找到扩展库的路径后,将modules下面的extern_name.so文件复制到扩展库的目录下,重新启动一下Apache进程: [cnangel@localhost ext_name]$which httpd /usr/bin/httpd [cnangel@localhost ext_name]$sudo /usr/bin/httpd -k stop [cnangel@localhost ext_name]$sudo /usr/bin/httpd -k start把这个样例ext_name.php复制到web路径上去,看看是否好使啦?下一节我们将详细讲一些Zend API的宏在ext_name.cpp中的一些复杂应用。 |