php拓展开发之模块全局变量

来源:互联网 发布:喝咖啡会难怀孕吗 知乎 编辑:程序博客网 时间:2024/05/21 06:38

1.什么是模块全局变量

模块全局变量存在于模块初始化(PHP_MINIT_FUNCTION(extname))到模块注销(PHP_MSHUTDOWN_FUNCTION(extname))期间。在不同的环境下,在这期间存在一个或多个请求,共享模块全局变量。

2.模块变量类型的定义

在引入php相关头文件后,定义:

PHP_BEGIN_MODULE_GLOBALS(extname)    std::string name;    std::string version;PHP_END_MODULE_GLOBALS(extname)

PHP_BEGIN_MODULE_GLOBALS 宏的定义为:

#define ZEND_BEGIN_MODULE_GLOBALS(module_name) \    typedef struct _zend_##module_name##_globals {

PHP_END_MODULE_GLOBALS 宏的定义为:

#define ZEND_END_MODULE_GLOBALS(module_name)    \    } zend_##module_name##_globals;

所以上面的模块变量定义展开来就是:

typedef struct _zend_extname_globals {    std::string name;    std::string version;} zend_extname_globals;

模块变量实际上是定义为一个 zend_extname_globals 类型。

3.模块变量的定义

在模块文件的顶部加上:

ZEND_DECLARE_MODULE_GLOBALS(extname)

ZEND_DECLARE_MODULE_GLOBALS 宏在线程安全的环境下的定义为:

#define ZEND_DECLARE_MODULE_GLOBALS(module_name) \    ts_rsrc_id module_name##_globals_id;

也就是,在线程安全下,模块变量的定义,展开来是定义了一个 名为extname_globals_id 的 ts_rsrc_id 类型的变量,改变量用于定位模块变量的存取位置,后面会讲到。


ZEND_DECLARE_MODULE_GLOBALS 宏在非线程安全下的定义为:

#define ZEND_DECLARE_MODULE_GLOBALS(module_name) \    zend_##module_name##_globals module_name##_globals;

展开来就是定义了一个类型为该模块变量结构体的变量 extname_globals。可以通过该变量直接存取模块全局变量。


另外还有一个宏: ZEND_EXTERN_MODULE_GLOBALS(module_name) ,用于在其他文件声明模块全局变量。


4.模块全局变量初始化

在PHP_MINIT_FUNCTION(extname){ //这里} 里面:

ZEND_INIT_MODULE_GLOBALS(extname,php_extname_init_globals_ctor,php_extname_init_globals_dtor)

ZEND_INIT_MODULE_GLOBALS(extname,globals_ctor,global_dtor) 的线程安全下的定义为:

#define ZEND_INIT_MODULE_GLOBALS(module_name,globals_ctor,globals_dtor) \    ts_allocate_id(&module_name##_globals_id,sizeof(zend_##module_name##_globals),(ts_allocate_ctor) globals_ctor,(ts_allocate_dtor) globals_dtor);

也就是初始化 extname_globals_id。


ZEND_INIT_MODULE_GLOBALS(extname,globals_ctor,global_dtor) 的非线程安全下的定义为:

#define ZEND_INIT_MODULE_GLOBALS(module_name,globals_ctor,globals_dtor) \    globals_ctor(&module_name##_globals);

在非线程下,只是简单的调用global_ctor来初始化 extname_globals


其中的global_ctor 是初始化模块全局变量函数,global_dtor是注销模块全局变量函数。他们可以在PHP_MINIT_FUNCTION调用前像下面那样子定义:

static void php_extname_init_globals_ctor(zend_extname_globals *extname_globals TSRMLS_DC){    extname_globals->name = "extname";    extname_globals->version = "v0.1";}static void php_extname_init_globals_dtor(zend_extname_globals *extname_globals TSRMLS_DC){     //如果模块有申请堆空间的话,在这里释放}

另外,根据我们看到的,非线程情况下,我们需要在PHP_MSHUTDOWN_FUNCTION 里手动调用php_extname_init_globals_dtor,以释放资源。

5.模块全局变量的存取

为了方便存取,我们可以定义EXTNAME(name)宏来统一在线程或非线程下的存取。

#ifdef ZTS#define EXTNAME_G(name) TSRMG(extname_globals_id,zend_extname_globals*,name)#else#define EXTNAME_G(name) (extname_globals.name)#endif


然后,就可以通过,EXTNAME_G(name) ,EXTNAME_G(version)来存取模块全局变量了。


原创粉丝点击