PHP扩展开发 ini配置项定义

扩展 jlog

首先、在 php_jlog.h 文件中添加如下代码。使用扩展工具生成的扩展框架中包含下面的代码,只是默认情况下是注释的,可以把注释打开然后修改。

ZEND_BEGIN_MODULE_GLOBALS(jlog)

zend_bool enable_thread;

ZEND_END_MODULE_GLOBALS(jlog)

然后、在jlog.c 文件中添加如下代码。

ZEND_DECLARE_MODULE_GLOBALS(jlog);

PHP_INI_BEGIN()

STD_PHP_INI_ENTRY("jlog.enable_thread", "1", PHP_INI_SYSTEM, OnUpdateBool, enable_thread, zend_jlog_globals, jlog_globals)

PHP_INI_END()

PHP_GINIT_FUNCTION(jlog)

{

JLOG_G(enable_thread) = 1;

}

最后需要在PHP_MINIT_FUNCTION(jlog) 中注册全局变量

PHP_MINIT_FUNCTION(jlog)

{

REGISTER_INI_ENTRIES(); // 注册全局变量入口

server_start = 0;

if(!queue_init()) {

php_error(E_ERROR,"队列初始化失败\n");

}

return SUCCESS;

}

// 在生命周期最后销毁这些全局变量

PHP_MSHUTDOWN_FUNCTION(jlog)

{

UNREGISTER_INI_ENTRIES(); // 销毁

if(server_start == 1) {

server_start = 0;

if(JLOG_G(enable_thread)) {

while (!checkQueueEmpty() || !idle) {}

pthread_cancel(tid);

pthread_join(tid, NULL);

}

}

free(jlog_queue);

return SUCCESS;

}

到此,基本流程就完成了。但是我们注意到在上面新增了PHP_GINIT_FUNCTION(jlog) 。 这是用来初始化全局变量的。但是默认情况下这是不会执行的。需要我们来手动指定其调用。

jlog.c默认的有个变量

zend_module_entry pen_module_entry = {

STANDARD_MODULE_HEADER,

"pen",

pen_functions,

PHP_MINIT(pen),

PHP_MSHUTDOWN(pen),

PHP_RINIT(pen), /* Replace with NULL if there's nothing to do at request start */

PHP_RSHUTDOWN(pen), /* Replace with NULL if there's nothing to do at request end */

PHP_MINFO(pen),

PHP_PEN_VERSION,

STANDARD_MODULE_PROPERTIES

};

我们需要对这个变量的值进行修改,因为STANDARD_MODULE_PROPERTIES宏定义如下

#define STANDARD_MODULE_PROPERTIES \

NO_MODULE_GLOBALS, NULL, STANDARD_MODULE_PROPERTIES_EX

// 其中有个宏 NO_MODULE_GLOBALS 由名字就可以知道禁止了全局变量

#define NO_MODULE_GLOBALS 0, NULL, NULL, NULL

所以我们需要将jlog.c 中的变量进行修改

zend_module_entry jlog_module_entry = {

STANDARD_MODULE_HEADER,

"jlog",

jlog_functions,

PHP_MINIT(jlog),

PHP_MSHUTDOWN(jlog),

PHP_RINIT(jlog), /* Replace with NULL if there's nothing to do at request start */

PHP_RSHUTDOWN(jlog), /* Replace with NULL if there's nothing to do at request end */

PHP_MINFO(jlog),

PHP_JLOG_VERSION,

PHP_MODULE_GLOBALS(jlog),

PHP_GINIT(jlog), // PHP_GINIT_FUNCTION(jlog) 的调用

NULL,

NULL,

STANDARD_MODULE_PROPERTIES_EX

};

上面的变量是由zend_module_entry 定义,而zend_module_entry结构体如下

typedefstruct _zend_module_entryzend_module_entry;

struct _zend_module_entry {

unsignedshort size;

unsignedint zend_api;

unsignedchar zend_debug;

unsignedchar zts;

conststruct _zend_ini_entry *ini_entry;

conststruct _zend_module_dep *deps;

constchar *name;

conststruct _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);

constchar *version;

size_t globals_size;

#ifdef ZTS

ts_rsrc_id* globals_id_ptr;

#else

void* globals_ptr;

#endif

void (*globals_ctor)(void *global TSRMLS_DC);

void (*globals_dtor)(void *global TSRMLS_DC);

int (*post_deactivate_func)(void);

int module_started;

unsignedchar type;

void *handle;

int module_number;

constchar *build_id;

};

这里定义了一个php扩展模块的入口,里面定义了一个模块整个生命周期所需要的信息。

到此为止,已经是一个完整的扩展了。但是,还有一个问题,这个扩展只是对于ZTS版本的php有效。对于NTS版本的在编译的时候会报错。原因就是下面这段代码

PHP_GINIT_FUNCTION(jlog)

{

JLOG_G(enable_thread) = 1;

}

按照php_jlog.h 中定义的

#ifdef ZTS

#define JLOG_G(v) TSRMG(jlog_globals_id, zend_jlog_globals *, v)

externint jlog_globals_id;

#else

#define JLOG_G(v) (jlog_globals.v)

extern zend_jlog_globals jlog_globals;

#endif

在NTS版本中,JLOG_G(v) 的定义是jlog_globals.v 。 在PHP_GINIT_FUNXTION(jlog)函数中直接使用宏JLOG_G(enable_thread) 在编译过程中是有问题的。此时的jlog_globals是一个指针变量,所以 jlog_globals.v 是会报错的。因此将PHP_GINIT_FUNCTION(jlog)修改如下

PHP_GINIT_FUNCTION(jlog)

{

jlog_globals->enable_thread = 1;

}

则编译的时候则不会报错。

至于为什么NTS版本会出现这种情况,现在还没有找到具体原因,等后续研究找到原因后再回来补上,先做个TODO

本文转载自:迹忆客(https://www.jiyik.com)

以上是 PHP扩展开发 ini配置项定义 的全部内容, 来源链接: utcz.com/z/290186.html

回到顶部