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()来代替ht
return_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_connect
handler 负责处理这个接口函数的指针。
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}标志数组的结束
四、声明Zend模块扩展结构
此块信息必须存储在zend_module_entry结构中,包含模块的必要信息。例如,初始化模块函数指针,模块的名称,版本信息等。
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;
参数 描述
size, zend_api, zend_debug and zts 通常使用STANDARD_MODULE_HEADER来填充,
name 扩展的名称
functions 指向zend_functions_entry指针
module_startup_func 模块初始化时被调用的函数指针。用来放一些初始化步骤。初始化过程中出现故障返回FAILURE,成功返回SUCCESS。声明一个初始化函数使用ZEND_MINIT
module_shutdown_func 模块被关闭时调用的函数指针,同来用来做一次性的析构步骤。如释放资源。
成功返回SUCESS,失败返回FAILURE,未使用返回NULL。声明使用ZEND_MSHUTDOWN
request_startup_func 每处理一次请求前调用此函数。成功SUCESS,失败FAILURE,未使用返回NULL。声明使用ZEND_RINIT。
从WEB来解释,就是每次请求调用此函数。
request_startup_func 每处理一次请求前后调用此函数。成功SUCESS,失败FAILURE,未使用返回NULL。声明使用ZEND_RINIT。
request_shutdown_func 每处理一次请求结束后调用此函数。成功SUCESS,失败FAILURE,未使用返回NULL。声明使用ZEND_RSHUTDOWN。
info_func 当调用phpinfo()时打印出的关于此扩展的信息。
这个信息就是由此函数来输出的。
声明使用ZEND_MINFO
version 扩展的字符串版本号。若无版本号,可以使用NO_VERSION_YET
[more] 多余不重要的参数,可以使用宏STANDARD_MODULE_PROPERTIES_EX或STANDARD_MODULE_PROPERTIES
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函数
下面是名为test的PHP扩展的文件,通过上面的介绍,对比下面的代码,就会比较清晰的理解PHP扩展开发的步骤。
#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[] */
};
/* }}} */

/* 模块结构,声明了startupshutdown、模块名及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_TEST
ZEND_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);
}

未经允许不得转载:SuperMan's blog » PHP扩展模块结构

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址