PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("myfile.global_value", "42", PHP_INI_ALL, OnUpdateInt, global_value, zend_myfile_globals, myfile_globals)
STD_PHP_INI_ENTRY("myfile.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_myfile_globals, myfile_globals)
PHP_INI_END()
除了STD_PHP_INI_ENTRY()其他宏也能够使用,但这个宏是最常用的,可以满足大多数需要(参看表对宏参数的说明):
复制代码 代码如下:
STD_PHP_INI_ENTRY(name, default_value, modifiable, on_modify, property_name, struct_type, struct_ptr)
STD_PHP_INI_ENTRY 宏参数表
参数 含义
name INI条目名
default_value 如果没有在INI文件中指定,条目的默认值。默认值始终是一个字符串。
modifiable 设定在何种环境下INI条目可以被更改的位域。可以的值是:
• PHP_INI_SYSTEM. 能够在php.ini或http.conf等系统文件更改
• PHP_INI_PERDIR. 能够在 .htaccess中更改
• PHP_INI_USER. 能够被用户脚本更改
• PHP_INI_ALL. 能够在所有地方更改
on_modify 处理INI条目更改的回调函数。你不需自己编写处理程序,使用下面提供的函数。包括:
• OnUpdateInt
• OnUpdateString
• OnUpdateBool
• OnUpdateStringUnempty
• OnUpdateReal
property_name 应当被更新的变量名
struct_type 变量驻留的结构类型。因为通常使用全局变量机制,所以这个类型自动被定义,类似于zend_myfile_globals。
struct_ptr 全局结构名。如果使用全局变量机制,该名为myfile_globals。
最后,为了使自定义INI条目机制正常工作,你需要分别去掉PHP_MINIT_FUNCTION(myfile)中的REGISTER_INI_ENTRIES()调用和PHP_MSHUTDOWN_FUNCTION(myfile)中的UNREGISTER_INI_ENTRIES()的注释。
访问两个示例全局变量中的一个与在扩展里编写MYFILE_G(global_value) 和MYFILE_G(global_string)一样简单。
如果你把下面的两行放在php.ini中,MYFILE_G(global_value)的值会变为99。
复制代码 代码如下:
; php.ini – The following line sets the INI entry myfile.global_value to 99.myfile.global_value = 9
线程安全资源管理宏
现在,你肯定注意到以TSRM(线程安全资源管理器)开头的宏随处使用。这些宏提供给扩展拥有独自的全局变量的可能,正如前面提到的。
当编写PHP扩展时,无论是在多进程或多线程环境中,都是依靠这一机制访问扩展自己的全局变量。如果使用全局变量访问宏(例如MYFILE_G()宏),需要确保TSRM上下文信息出现在当前函数中。基于性能的原因,Zend引擎试图把这个上下文信息作为参数传递到更多的地方,包括PHP_FUNCTION()的定义。正因为这样,在PHP_FUNCTION()内当编写的代码使用访问宏(例如MYFILE_G()宏)时,不需要做任何特殊的声明。然而,如果PHP函数调用其他需要访问全局变量的C函数,要么把上下文作为一个额外的参数传递给C函数,要么提取上下文(要慢点)。
在需要访问全局变量的代码块开头使用TSRMLS_FETCH()来提取上下文。例如:
复制代码 代码如下:
void myfunc(){
TSRMLS_FETCH();
MYFILE_G(myglobal) = 2;
}
如果希望让代码更加优化,更好的办法是直接传递上下文给函数(正如前面叙述的,PHP_FUNCTION()范围内自动可用)。可以使用TSRMLS_C(C表示调用Call)和TSRMLS_CC(CC边式调用Call和逗号Comma)宏。前者应当用于仅当上下文作为一个单独的参数,后者应用于接受多个参数的函数。在后一种情况中,因为根据取名,逗号在上下文的前面,所以TSRMLS_CC不能是第一个函数参。
在函数原形中,可以分别使用TSRMLS_D和TSRMLS_DC宏声名正在接收上下文。
下面是前一例子的重写,利用了参数传递上下文。
复制代码 代码如下: