PHP扩展模块结构
所有PHP扩展遵循一个共同的结构1、头文件包含(包括所有需要的宏、API)2、C声明导出函数3、声明Zend函数块
一、头文件包含通过ext_seketon新建的扩展,默认都会新建一个php_extname.h的头文件。其中包含了php.h,该文件导入Zend基本的宏和API。
二、声明导出函数ZEND_FUNCTION(my_function),提供PHP中调用的函数。展开此宏:void zif_my_function(INTERNAL_FUNCTION_PARAMETERS)void zif_my_function(int ht, zval *return_value, zval *this_ptr, int return_value_users, zend_executor_globals *executor_globals);参数的作用:参数描述ht接收的参数个数。考虑向后兼容,使用ZEND_NUM_ARGS()来代替htreturn_value传递到PHP接口的返回值。this_ptr如果这个函数是对象中的方法,this_ptr返回当前对象return_value_used标志最终这个函数返回到PHP接口中是否被使用。executor_globals指向zend引擎的全局设置。
三、声明Zend函数块建立zend_function_entry数组,提供给ZEND作为PHP的接口。
typedef struct _zend_function_entry { char *fname; void (*handler)(INTERNAL_FUNCTION_PARAMETERS); unsigned char *func_arg_types;} zend_function_entry;参数描述fname提供给PHP中调用的函数名。例如mysql_connecthandler负责处理这个接口函数的指针。func_arg_types标记参数。可以设置为NULL
static const zend_function_entry mysql_functions[] = { PHP_FE(mysql_connect, arginfo_mysql_connect) PHP_FE(mysql_pconnect, arginfo_mysql_pconnect) PHP_FE(mysql_close, arginfo__optional_mysql_link) PHP_FE(mysql_select_db, arginfo_mysql_select_db) {NULL, NULL, NULL}}上述是mysql扩展中定义的zend_function_entry的部分。其中{NULL, NULL, NULL}标志数组的结束
struct _zend_module_entry { unsigned short size; unsigned int zend_api; unsigned char zend_debug; unsigned char zts; char *name; zend_function_entry *functions; int (*module_startup_func)(INIT_FUNC_ARGS); int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS); int (*request_startup_func)(INIT_FUNC_ARGS); int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS); void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS); char *version; [more]};
typedef struct _zend_module_entry zend_module_entry;
zend_module_entry firstmod_module_entry ={ STANDARD_MODULE_HEADER, "New Module", firstmod_functions, NULL, NULL, NULL, NULL, NULL, NO_VERSION_YET, STANDARD_MODULE_PROPERTIES,};这是一个最基本的模块结构,模块名“New Module”,函数列表为firstmod_functions,未设置startup、shutdown函数
#ifdef HAVE_CONFIG_H#include "config.h"#endif/*包含ZEND提供的API、宏和基本的PHP内置函数,例如php_trim*/#include "php.h"#include "php_ini.h"#include "ext/standard/info.h"#include "php_test.h"/* 开启模块中的全局变量 */ZEND_DECLARE_MODULE_GLOBALS(test)/* True global resources - no need for thread safety here */static int le_test;/* * 声明函数数组,提供给PHP使用*/const zend_function_entry test_functions[] = { PHP_FE(my_function, NULL) /* For testing, remove later. */ PHP_FE_END /* Must be the last line in test_functions[] */};/* }}} *//* 模块结构,声明了startup\shutdown、模块名及phpinfo打印时的函数*/zend_module_entry test_module_entry = {#if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER,#endif "test", test_functions, PHP_MINIT(test), PHP_MSHUTDOWN(test), PHP_RINIT(test), /* Replace with NULL if there's nothing to do at request start */ PHP_RSHUTDOWN(test), /* Replace with NULL if there's nothing to do at request end */ PHP_MINFO(test),#if ZEND_MODULE_API_NO >= 20010901 "0.1", /* Replace with version number for your extension */#endif STANDARD_MODULE_PROPERTIES};#ifdef COMPILE_DL_TESTZEND_GET_MODULE(test)#endif/* 从php.ini配置文件中读取配置信息 */PHP_INI_BEGIN() STD_PHP_INI_ENTRY("test.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_test_globals, test_globals) STD_PHP_INI_ENTRY("test.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_test_globals, test_globals)PHP_INI_END()/* 初始化全局变量默认值 */static void php_test_init_globals(zend_test_globals *test_globals){ test_globals->global_value = 0; test_globals->global_string = NULL;}/* 模块第一次加载时被调用*/PHP_MINIT_FUNCTION(test){ /* 注册全局变量 */ REGISTER_INI_ENTRIES(); return SUCCESS;}/* 模块关闭时调用*/PHP_MSHUTDOWN_FUNCTION(test){ /* 释放全局变量 */ UNREGISTER_INI_ENTRIES(); return SUCCESS;}/* 每次请求前调用*/PHP_RINIT_FUNCTION(test){ return SUCCESS;}/* /* 每次请求结束时调用*/PHP_RSHUTDOWN_FUNCTION(test){ return SUCCESS;}/* phpinfo()输出扩展信息*/PHP_MINFO_FUNCTION(test){ php_info_print_table_start(); php_info_print_table_header(2, "test support", "enabled"); php_info_print_table_end(); /* 是否输出php.ini中的配置信息 DISPLAY_INI_ENTRIES(); */}/* 定义函数my_function提供给PHP中使用 */PHP_FUNCTION(my_function){ char *arg = NULL; int arg_len, len; char *strg; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { return; } len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "test", arg); RETURN_STRINGL(strg, len, 0);}