PHP Extension及Zend_Module结构分析
以上可以看成是为开发PHP扩展而做的准备工作,下面就要编写核心代码了。上文说过,编写PHP扩展是基于Zend API和一些宏的,所以如果要编写核心代码,我们首先要弄清楚PHP Extension的结构。因为一个PHP Extension在C语言层面实际上就是一个zend_module_entry结构体,这点可以从“php_say_hello.h”中得到证实。打开“php_say_hello.h”,会看到里面有怎么一行:
say_hello_module_entry就是say_hello扩展的C语言对应元素,而关于其类型zend_module_entry的定义可以在PHP源代码的“Zend/zend_modules.h”文件里找到,下面代码是zend_module_entry的定义:
02
03 struct _zend_module_entry {
04 unsigned short size;
05 unsigned int zend_api;
06 unsigned char zend_debug;
07 unsigned char zts;
08 const struct _zend_ini_entry *ini_entry;
09 const struct _zend_module_dep *deps;
10 const char *name;
11 const struct _zend_function_entry *functions;
12 int (*module_startup_func)(INIT_FUNC_ARGS);
13 int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS);
14 int (*request_startup_func)(INIT_FUNC_ARGS);
15 int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS);
16 void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS);
17 const char *version;
18 size_t globals_size;
19 #ifdef ZTS
20 ts_rsrc_id* globals_id_ptr;
21 #else
22 void* globals_ptr;
23 #endif
24 void (*globals_ctor)(void *global TSRMLS_DC);
25 void (*globals_dtor)(void *global TSRMLS_DC);
26 int (*post_deactivate_func)(void);
27 int module_started;
28 unsigned char type;
29 void *handle;
30 int module_number;
31 char *build_id;
32 };
这个结构体可能看起来会让人有点头疼,不过我还是要解释一下里面的内容。因为这就是PHP Extension的原型,如果不搞清楚,就没法开发PHP Extension了。当然,我就不一一对每个字段进行解释了,只拣关键的、这篇文章会用到的字段说,因为许多字段并不需要我们手工填写,而是可以使用某些预定义的宏填充。
第7个字段“name”,这个字段是此PHP Extension的名字,在本例中就是“say_hello”。
第8个字段“functions”,这个将存放我们在此扩展中定义的函数的引用,具体结构不再分析,有兴趣的朋友可以阅读_zend_function_entry的源代码。具体编写代码时这里会有相应的宏。
第9-12个字段分别是四个函数指针,这四个函数会在相应时机被调用,分别是“扩展模块加载时”、“扩展模块卸载时”、“每个请求开始时”和“每个请求结束时”。这四个函数可以看成是一种拦截机制,主要用于相应时机的资源分配、释放等相关操作。
第13个字段“info_func”也是一个函数指针,这个指针指向的函数会在执行phpinfo()时被调用,用于显示自定义模块信息。
第14个字段“version”是模块的版本。
(关于zend_module_entry更详尽的介绍请参考这里)