如果你懒得弄清楚PHP扩展包目录结构的全部内容,那么里面有三个文件你必须注意:
config.m4:这是Unix环境下的Build System配置文件,后面将会通过它生成配置和安装。
php_say_hello.h:这个文件是扩展模块的头文件。遵循C语言一贯的作风,这个里面可以放置一些自定义的结构体、全局变量等等。
say_hello.c:这个就是扩展模块的主程序文件了,最终的扩展模块各个函数入口都在这里。当然,你可以将所有程序代码都塞到这里面,也可以遵循模块化思想,将各个功能模块放到不同文件中。
下面的内容主要围绕这三个文件展开。
Unix Build System配置
开发PHP扩展组件的第一步不是写实现代码,而是要先配置好Build System选项。由于我们是在Linux下开发,所以这里的配置主要与config.m4有关。
关于Build System配置这一块,要是写起来能写一大堆,而且与Unix系统很多东西相关,就算我有兴趣写估计大家也没兴趣看,所以这里我们从略,只拣关键地方说一下,关于config.m4更多细节可以参考这里。
打开生成的config.m4文件,内容大致如下:
dnl $Id___FCKpd___4nbsp; dnl config.m4 for extension say_hello dnl Comments in this file start with the string dnl. dnl Remove where necessary. This file will not work dnl without editing. dnl If your extension references something external, use with: dnl PHP_ARG_WITH(say_hello, for say_hello support, dnl Make sure that the comment is aligned: dnl [ --with-say_hello Include say_hello support]) dnl Otherwise use enable: dnl PHP_ARG_ENABLE(say_hello, whether to enable say_hello support, dnl Make sure that the comment is aligned: dnl [ --enable-say_hello Enable say_hello support]) if test "$PHP_SAY_HELLO" != "no"; then dnl Write more examples of tests here... dnl # --with-say_hello -> check with-path dnl SEARCH_PATH="/usr/local /usr" # you might want to change this dnl SEARCH_FOR="/include/say_hello.h" # you most likely want to change this dnl if test -r $PHP_SAY_HELLO/$SEARCH_FOR; then # path given as parameter dnl SAY_HELLO_DIR=$PHP_SAY_HELLO dnl else # search default path list dnl AC_MSG_CHECKING([for say_hello files in default path]) dnl for i in $SEARCH_PATH ; do dnl if test -r $i/$SEARCH_FOR; then dnl SAY_HELLO_DIR=$i dnl AC_MSG_RESULT(found in $i) dnl fi dnl done dnl fi dnl dnl if test -z "$SAY_HELLO_DIR"; then dnl AC_MSG_RESULT([not found]) dnl AC_MSG_ERROR([Please reinstall the say_hello distribution]) dnl fi dnl # --with-say_hello -> add include path dnl PHP_ADD_INCLUDE($SAY_HELLO_DIR/include) dnl # --with-say_hello -> check for lib and symbol presence dnl LIBNAME=say_hello # you may want to change this dnl LIBSYMBOL=say_hello # you most likely want to change this dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, dnl [ dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SAY_HELLO_DIR/lib, SAY_HELLO_SHARED_LIBADD) dnl AC_DEFINE(HAVE_SAY_HELLOLIB,1,[ ]) dnl ],[ dnl AC_MSG_ERROR([wrong say_hello lib version or lib not found]) dnl ],[ dnl -L$SAY_HELLO_DIR/lib -lm dnl ]) dnl dnl PHP_SUBST(SAY_HELLO_SHARED_LIBADD) PHP_NEW_EXTENSION(say_hello, say_hello.c, $ext_shared) fi 不要看这么多,因为所有以“dnl”开头的全是注释,所以真正起作用没几行。这里需要配置的只有下面几行:
dnl If your extension references something external, use with: dnl PHP_ARG_WITH(say_hello, for say_hello support, dnl Make sure that the comment is aligned: dnl [ --with-say_hello Include say_hello support]) dnl Otherwise use enable: dnl PHP_ARG_ENABLE(say_hello, whether to enable say_hello support, dnl Make sure that the comment is aligned: dnl [ --enable-say_hello Enable say_hello support]) 我想大家也都能看明白,意思就是“如果你的扩展引用了外部组件,使用…,否则使用…”。我们的say_hello扩展并没有引用外部组件,所以将“Otherwise use enable”下面三行的“dnl”去掉,改为:
dnl それ以外の場合は、enable を使用します: PHP_ARG_ENABLE(say_hello、say_hello サポートを有効にするかどうか、コメントが整列していることを確認してください: [ --enable-say_hello Say_hello サポートを有効にする]) 保存すると、ビルド システムの構成は完了です。
PHP 拡張機能と Zend_Module 構造解析
上記は PHP 拡張機能を開発するための準備として見ることができ、次にコア コードを記述します。上で述べたように、PHP 拡張機能の作成は Zend API といくつかのマクロに基づいているため、コア コードを作成したい場合は、まず PHP 拡張機能の構造を理解する必要があります。 PHP Extension は実際には C 言語レベルの zend_module_entry 構造体であるため、「php_say_hello.h」で確認できます。 「php_say_hello.h」を開くと、次の行が表示されます:
extern zend_module_entry Say_hello_module_entry; Say_hello_module_entry は、say_hello 拡張機能に対応する C 言語の要素であり、そのタイプ zend_module_entry の定義は、PHP ソース コードの「Zend/zend_modules.h」ファイルにあります。 zend_module_entry:
typedef struct _zend_module_entry zend_module_entry { unsigned short size; unsigned char zts; ; const char *name; const struct _zend_function_entry *関数; *module_startup_func)(INIT_FUNC_ARGS); int (*module_shutdown_func)(INIT_FUNC_ARGS); void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS); def ZTS ts_rsrc_id* globals_id_ptr; #それ以外 &n