时间:2021-07-01 10:21:17 帮助过:19人阅读
这时再用ls查看,会发现多了一个“say_hello”目录,进入这个目录,会发现ext_skel已经为我们建立好了say_hello的基本框架,如下图:
如果你懒得弄清楚PHP扩展包目录结构的全部内容,那么里面有三个文件你必须注意:
config.m4:这是Unix环境下的Build System配置文件,后面将会通过它生成配置和安装。
php_say_hello.h:这个文件是扩展模块的头文件。遵循C语言一贯的作风,这个里面可以放置一些自定义的结构体、全局变量等等。
say_hello.c:这个就是扩展模块的主程序文件了,最终的扩展模块各个函数入口都在这里。当然,你可以将所有程序代码都塞到这里面,也可以遵循模块化思想,将各个功能模块放到不同文件中。
下面的内容主要围绕这三个文件展开。
开发PHP扩展组件的第一步不是写实现代码,而是要先配置好Build System选项。由于我们是在Linux下开发,所以这里的配置主要与config.m4有关。
关于Build System配置这一块,要是写起来能写一大堆,而且与Unix系统很多东西相关,就算我有兴趣写估计大家也没兴趣看,所以这里我们从略,只拣关键地方说一下,关于config.m4更多细节可以参考这里。
打开生成的config.m4文件,内容大致如下:
代码如下:
输出表格内容。第一个参数是整形,指明这一行的列数,然后后面的参数是与列数等量的(char*)类型参数用于指定显示的文字。
- <br>dnl $Id$ <br>dnl config.m4 for extension say_hello <br>dnl Comments in this file start with the string 'dnl'. <br>dnl Remove where necessary. This file will not work <br>dnl without editing. <br>dnl If your extension references something external, use with: <br>dnl PHP_ARG_WITH(say_hello, for say_hello support, <br>dnl Make sure that the comment is aligned: <br>dnl [ --with-say_hello Include say_hello support]) <br>dnl Otherwise use enable: <br>dnl PHP_ARG_ENABLE(say_hello, whether to enable say_hello support, <br>dnl Make sure that the comment is aligned: <br>dnl [ --enable-say_hello Enable say_hello support]) <br>if test "$PHP_SAY_HELLO" != "no"; then <br>dnl Write more examples of tests here... <br>dnl # --with-say_hello -> check with-path <br>dnl SEARCH_PATH="/usr/local /usr" # you might want to change this <br>dnl SEARCH_FOR="/include/say_hello.h" # you most likely want to change this <br>dnl if test -r $PHP_SAY_HELLO/$SEARCH_FOR; then # path given as parameter <br>dnl SAY_HELLO_DIR=$PHP_SAY_HELLO <br>dnl else # search default path list <br>dnl AC_MSG_CHECKING([for say_hello files in default path]) <br>dnl for i in $SEARCH_PATH ; do <br>dnl if test -r $i/$SEARCH_FOR; then <br>dnl SAY_HELLO_DIR=$i <br>dnl AC_MSG_RESULT(found in $i) <br>dnl fi <br>dnl done <br>dnl fi <br>dnl <br>dnl if test -z "$SAY_HELLO_DIR"; then <br>dnl AC_MSG_RESULT([not found]) <br>dnl AC_MSG_ERROR([Please reinstall the say_hello distribution]) <br>dnl fi <br>dnl # --with-say_hello -> add include path <br>dnl PHP_ADD_INCLUDE($SAY_HELLO_DIR/include) <br>dnl # --with-say_hello -> check for lib and symbol presence <br>dnl LIBNAME=say_hello # you may want to change this <br>dnl LIBSYMBOL=say_hello # you most likely want to change this <br>dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, <br>dnl [ <br>dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SAY_HELLO_DIR/lib, SAY_HELLO_SHARED_LIBADD) <br>dnl AC_DEFINE(HAVE_SAY_HELLOLIB,1,[ ]) <br>dnl ],[ <br>dnl AC_MSG_ERROR([wrong say_hello lib version or lib not found]) <br>dnl ],[ <br>dnl -L$SAY_HELLO_DIR/lib -lm <br>dnl ]) <br>dnl <br>dnl PHP_SUBST(SAY_HELLO_SHARED_LIBADD) <br>PHP_NEW_EXTENSION(say_hello, say_hello.c, $ext_shared) <br>fi <br><br><p></p>
- <p>这个结构体可能看起来会让人有点头疼,不过我还是要解释一下里面的内容。因为这就是PHP Extension的原型,如果不搞清楚,就没法开发PHP Extension了。当然,我就不一一对每个字段进行解释了,只拣关键的、这篇文章会用到的字段说,因为许多字段并不需要我们手工填写,而是可以使用某些预定义的宏填充。</p>
- <p>第7个字段“name”,这个字段是此PHP Extension的名字,在本例中就是“say_hello”。</p>
- <p>第8个字段“functions”,这个将存放我们在此扩展中定义的函数的引用,具体结构不再分析,有兴趣的朋友可以阅读_zend_function_entry的源代码。具体编写代码时这里会有相应的宏。</p>
- <p>第9-12个字段分别是四个函数指针,这四个函数会在相应时机被调用,分别是“扩展模块加载时”、“扩展模块卸载时”、“每个请求开始时”和“每个请求结束时”。这四个函数可以看成是一种拦截机制,主要用于相应时机的资源分配、释放等相关操作。</p>
- <p>第13个字段“info_func”也是一个函数指针,这个指针指向的函数会在执行phpinfo()时被调用,用于显示自定义模块信息。</p>
- <p>第14个字段“version”是模块的版本。</p>
- <p>(关于zend_module_entry更详尽的介绍请参考这里)</p>
- <p>介绍完以上字段,我们可以看看“say_hello.c”中自动生成的“say_hello_module_entry”框架代码了。<br><span style="CURSOR: pointer" onclick="doCopy('code77236')"><u></u></span> 代码如下:</p><pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>/* {{{ say_hello_module_entry <br>*/ <br>zend_module_entry say_hello_module_entry = { <br>#if ZEND_MODULE_API_NO >= 20010901 <br>STANDARD_MODULE_HEADER, <br>#endif <br>"say_hello", <br>say_hello_functions, <br>PHP_MINIT(say_hello), <br>PHP_MSHUTDOWN(say_hello), <br>PHP_RINIT(say_hello), /* Replace with NULL if there's nothing to do at request start */ <br>PHP_RSHUTDOWN(say_hello), /* Replace with NULL if there's nothing to do at request end */ <br>PHP_MINFO(say_hello), <br>#if ZEND_MODULE_API_NO >= 20010901 <br>"0.1", /* Replace with version number for your extension */ <br>#endif <br>STANDARD_MODULE_PROPERTIES <br>}; <br>/* }}} */ <br><br><p></p></li><li><p>首先,宏“STANDARD_MODULE_HEADER”会生成前6个字段,“STANDARD_MODULE_PROPERTIES ”会生成“version”后的字段,所以现在我们还不用操心。而我们关心的几个字段,也都填写好或由宏生成好了,并且在“say_hello.c”的相应位置也生成了几个函数的框架。这里要注意,几个宏的参数均为“say_hello”,但这并不表示几个函数的名字全为“say_hello”,C语言中也不可能存在函数名重载机制。实际上,在开发PHP Extension的过程中,几乎处处都要用到Zend里预定义的各种宏,从全局变量到函数的定义甚至返回值,都不能按照“裸写”的方式来编写C语言,这是因为PHP的运行机制可能会导致命名冲突等问题,而这些宏会将函数等元素变换成一个内部名称,但这些对程序员都是透明的(除非你去阅读那些宏的代码),我们通过各种宏进行编程,而宏则为我们处理很多内部的东西。</p></li><li><p>写到这里,我们的任务就明了了:第一,如果需要在相应时机处理一些东西,那么需要填充各个拦截函数内容;第二,编写say_hello的功能函数,并将引用添加到say_hello_functions中。</p></li><li><h2>编写phpinfo()回调函数</h2></li><li><p>因为say_hello扩展在各个生命周期阶段并不需要做操作,所以我们只编写info_func的内容,上文说过,这个函数将在phpinfo()执行时被自动调用,用于显示扩展的信息。编写这个函数会用到四个函数:</p></li><li><p>php_info_print_table_start()——开始phpinfo表格。无参数。</p></li><li><p>php_info_print_table_header()——</p></li></ol></pre>输出表格头。第一个参数是整形,指明头的列数,然后后面的参数是与列数等量的(char*)类型参数用于指定显示的文字。<p></p>
- <p>php_info_print_table_row()——</p>
php_info_print_table_end()——结束phpinfo表格。无参数。
http://www.bkjia.com/PHPjc/322589.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/322589.htmlTechArticle摘要 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="/incl...