Apache中php扩展实战 ------ 获得ip的来源地址

jackxiang 2008-6-30 17:31 | |

1 前言

  • 主要目的让大家了解一下怎么做PHP语言的扩展,仍然以上次叙述的Perl的扩展的例子——获得IP来源地址为例。

2 前提条件

  • 假设你已经拥有了 LAMP (Linux+Apache+Mysql+PHP的缩写),并假设其安装路径分别是:
Apache:/usr/local/apache
Mysql:/usr/local/mysql
PHP:/usr/local/php
  • 目前所叙述的实例可能与 mysql 没有太多的关系,所以无关紧要,但是 PHP 是必须安装的;
  • 另外,需要 PHP 的源码,如果你没有,可以去 http://www.php.net 获取 PHP 源码,其源码路径位:
PHPSrc:/usr/local/php/src
  • 末了说句,本实例完全在 Linux 64 位平台下演示,若有出入,可以随时联系笔者。

3 流程及步骤

  • 其实制作PHP扩展非常简单, ext_skel 命令的帮助已说明得非常详细,如下所示:
[Cnangel@localhost ~]$cd /usr/local/php/src/ext
[Cnangel@localhost ext]$ext_skel --help
./ext_skel --extname=module [--proto=file] [--stubs=file] [--xml[=file]]
           [--skel=dir] [--full-xml] [--no-help]

  --extname=module   module is the name of your extension
  --proto=file       file contains prototypes of functions to create
  --stubs=file       generate only function stubs in file
  --xml              generate xml documentation to be added to phpdoc-cvs
  --skel=dir         path to the skeleton directory
  --full-xml         generate xml documentation for a self-contained extension
                     (not yet implemented)
  --no-help          don't try to be nice and create comments in the code
                     and helper functions to test if the module compiled
  • 尝试着创建一个扩展 getaddress
[Cnangel@localhost ext]$ext_skel --extname=getaddress
Creating directory getaddress
Creating basic files: config.m4 config.w32 .cvsignore getaddress.c php_getaddress.h CREDITS EXPERIMENTAL tests/001.phpt getaddress.php [done].

To use your new extension, you will have to execute the following steps:

1.  $ cd ..
2.  $ vi ext/getaddress/config.m4
3.  $ ./buildconf
4.  $ ./configure --[with|enable]-getaddress
5.  $ make
6.  $ ./php -f ext/getaddress/getaddress.php
7.  $ vi ext/getaddress/getaddress.c
8.  $ make

Repeat steps 3-6 until you are satisfied with ext/getaddress/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.
  • 上面的后续的帮助步骤已经说得比较清楚,一共 8 个步骤;

4 详细过程描述

4.1 建立扩展目录

  • 方便的 ext_skel 命令能帮助建立一个扩展模型 getaddress ,系统会自动建立一个 getaddress 目录,其文件会相应的生成在 getaddress 目录内;

4.2 描述及编辑config.m4

  • ext_skel 建立的目录里面一般有 config.m4 这个文件,这里面有一些基础的宏定义:
    • dnl 是注释;
    • PHP_ARG_WITH 或者 PHP_ARG_ENABLE 指定了PHP扩展模块的工作方式;
    • PHP_REQUIRE_CXX 用于指定这个扩展用到了C++;
    • PHP_ADD_INCLUDE 指定PHP扩展模块用到的头文件目录;
    • PHP_CHECK_LIBRARY 指定PHP扩展模块PHP_ADD_LIBRARY_WITH_PATH定义以及库连接错误信息等;
    • PHP_SUBST 用于说明这个扩展编译成动态链接库的形式;
    • PHP_NEW_EXTENSION 用于指定有哪些源文件应该被编译,文件和文件之间用空格隔开;
  • 这里指定PHP扩展模块的工作方式为 PHP_ARG_ENABLE ,需要修改config.m4文件为:
[Cnangel@localhost getaddress]vim config.m4
找到里面有类似几行:
    dnl PHP_ARG_WITH(getaddress, for getaddress support,
    dnl Make sure that the comment is aligned:
    dnl [  --with-getaddress             Include getaddress support])

    dnl Otherwise use enable:

    dnl PHP_ARG_ENABLE(getaddress, whether to enable getaddress support,
    dnl Make sure that the comment is aligned:
    dnl [  --enable-getaddress           Enable getaddress support])
修改成:
    dnl PHP_ARG_WITH(getaddress, for getaddress support,
    dnl Make sure that the comment is aligned:
    dnl [  --with-getaddress             Include getaddress support])

    dnl Otherwise use enable:

    PHP_ARG_ENABLE(getaddress, whether to enable getaddress support,
    Make sure that the comment is aligned:
    [  --enable-getaddress           Enable getaddress support])
  • 除了修改 config.m4 外,还需要修改的文件有 getaddress.cphp_getaddress.h 两个文件,下面会说到该文件的修改。

4.3 创建configure文件

  • 源码修改:进入源代码根目录,使用工具 buildconf 创建 configure 文件,其命令如下:
[Cnangel@localhost getaddress]cd /usr/local/php/src
[Cnangel@localhost src]./buildconf
  • 扩展修改:进入扩展目录,使用工具 phpize 创建 configure 文件,其目录如下:
[Cnangel@localhost getaddress]/usr/local/php/bin/phpize
Configuring for:
PHP Api Version:         20041225
Zend Module Api No:      20060613
Zend Extension Api No:   220060519

4.4 创建Makefile文件

  • 上个步骤中创建了 configure 文件,记住,一般在类unix系统中, configure 文件是一个可执行文件,用来创建编译过程中所用到的make命令所需要的Makefile文件,其创建过程如下:
./configure --enable-getaddress --with-apxs=/usr/local/apache/bin/apxs --with-php-config=/usr/local/php/bin/php-config
  • 注意,如果你写的扩展与apache有关,则需要关联apxs,产生apache的modules。

4.5 编译过程

  • 编译过程是一个调试过程,出现错误了需要检查 config.m4getaddress.cphp_getaddress.h 这几个文件是否编写正确,编译的过程十分简单,命令如下:
make

4.6 安装扩展模块

  • 安装扩展模块一般有两种安装,一种是直接:
make install
  • 结果会安装到: /usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/ 目录,然后在 php.ini 里面通过 extension_dir 将该目录设置为php的扩展目录,并在php.ini中打开这个扩展:
extension=getaddress.so
  • 另外一种是直接复制。一般经过编译过程这个步骤后,会在 getaddress 目录下生成一个目录: modules ,该目录下面有一个已经编译好的.so文件,如果是静态编译,可能是.a或.la;把该文件复制到一个目录下,比如: /usr/loca/php/ext/ ,然后直接调用函数 dl 来调用其 api。

4.7 运行测试

  • getaddress 目录下有一个 getaddress.php 文件专门用来测试你的扩展模块是否正确运行,该文件即可以作为 CGI 来运行又可以当作脚本执行,命令如下:
[Cnangel@localhost getaddress]php -f getaddress.php
Functions available in the test extension:
confirm_getaddress_compiled

Congratulations! You have successfully modified ext/getaddress/config.m4. Module getaddress is now compiled into PHP.

4.8 增添PHP扩展模块函数

  • 上述讲了这么多,这节才是最主要的。PHP扩展模块主要有三个方面的作用:
    1. 增加PHP基础函数没有的功能或更加 OOP(Object Oriented Programming) 的思想供工程调用;
    2. PHP的扩展一般是汇编、C/C++等编译性语言缩写,二进制运行消耗时间比解释性语言实现同样的功能少得多;
    3. 由于PHP扩展一般是二进制的,所以一般来说不开源,很方便的保护了版权,能够进行商业运用。
  • 默认的 getaddress.c 中, zend_function_entry 是导出函数列表, zend_module_entry 描述了模块的信息。
  • 编写代码应该注意:
    1. 如果是C++开发,记住把getaddress.c的后缀改为cpp,并用extern "C"来把c相关代码包起来;

5 Bugs

  • 在64位机器上和32位机器上会出现很大的差异,主要在QQWry.c文件;
  • 多个引用php函数会出现corp dump情况,具体原因还未查清;

6 实例代码

  • 注意,修复一处Bug:将
 Z_STRVAL_P(file) == NULL
代替
 Z_STRLEN_P(file) == 0

7 总结

  • 由于作者对C指针运用不太熟练,所以在操作指针时,往往会出现corp dump,这方面有待加强;
  • 就PHP扩展来说,涵盖的面比较广,需要丰富的知识面做铺垫才能做好一个优秀的扩展。


参考:
http://tech.ddvip.com/2009-09/1252583445132022.html

作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:http://jackxiang.com/post/1104/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!


最后编辑: jackxiang 编辑于2009-10-23 21:43
评论列表
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]