介绍完以上字段,我们可以看看“say_hello.c”中自动生成的“say_hello_module_entry”框架代码了。
02 */
03 zend_module_entry say_hello_module_entry = {
04 #if ZEND_MODULE_API_NO >= 20010901
05 STANDARD_MODULE_HEADER,
06 #endif
07 "say_hello",
08 say_hello_functions,
09 PHP_MINIT(say_hello),
10 PHP_MSHUTDOWN(say_hello),
11 PHP_RINIT(say_hello), /* Replace with NULL if there's nothing to do at request start */
12 PHP_RSHUTDOWN(say_hello), /* Replace with NULL if there's nothing to do at request end */
13 PHP_MINFO(say_hello),
14 #if ZEND_MODULE_API_NO >= 20010901
15 "0.1", /* Replace with version number for your extension */
16 #endif
17 STANDARD_MODULE_PROPERTIES
18 };
19 /* }}} */
首先,宏“STANDARD_MODULE_HEADER”会生成前6个字段,“STANDARD_MODULE_PROPERTIES ”会生成“version”后的字段,所以现在我们还不用操心。而我们关心的几个字段,也都填写好或由宏生成好了,并且在“say_hello.c”的相应位置也生成了几个函数的框架。这里要注意,几个宏的参数均为“say_hello”,但这并不表示几个函数的名字全为“say_hello”,C语言中也不可能存在函数名重载机制。实际上,在开发PHP Extension的过程中,几乎处处都要用到Zend里预定义的各种宏,从全局变量到函数的定义甚至返回值,都不能按照“裸写”的方式来编写C语言,这是因为PHP的运行机制可能会导致命名冲突等问题,而这些宏会将函数等元素变换成一个内部名称,但这些对程序员都是透明的(除非你去阅读那些宏的代码),我们通过各种宏进行编程,而宏则为我们处理很多内部的东西。
写到这里,我们的任务就明了了:第一,如果需要在相应时机处理一些东西,那么需要填充各个拦截函数内容;第二,编写say_hello的功能函数,并将引用添加到say_hello_functions中。
编写phpinfo()回调函数
因为say_hello扩展在各个生命周期阶段并不需要做操作,所以我们只编写info_func的内容,上文说过,这个函数将在phpinfo()执行时被自动调用,用于显示扩展的信息。编写这个函数会用到四个函数:
php_info_print_table_start()——开始phpinfo表格。无参数。
php_info_print_table_header()——输出表格头。第一个参数是整形,指明头的列数,然后后面的参数是与列数等量的(char*)类型参数用于指定显示的文字。
php_info_print_table_row()——输出表格内容。第一个参数是整形,指明这一行的列数,然后后面的参数是与列数等量的(char*)类型参数用于指定显示的文字。
php_info_print_table_end()——结束phpinfo表格。无参数。
下面是“say_hello.c”中需要编写的info_func的具体代码:
02 */
03 PHP_MINFO_FUNCTION(say_hello)
04 {
05 php_info_print_table_start();
06 php_info_print_table_header(2, "say_hello support", "enabled");
07 php_info_print_table_row(2, "author", "Zhang Yang"); /* Replace with your name */
08 php_info_print_table_end();
09
10 /* Remove comments if you have entries in php.ini
11 DISPLAY_INI_ENTRIES();
12 */
13 }
14 /* }}} */
可以看到我们编写了两行内容、组件是否可用以及作者信息。