PHP扩展暴露全局变量有五种方法:一、用zend_register_ini_entries注册可配置INI变量;二、用zend_hash_str_update写入EG(symbol_table)注入常量;三、用REGISTER_GLOBALS宏绑定模块私有结构体;四、用ZEND_MODULE_STARTUP_D宏注册运行时zval;五、通过类常量间接暴露状态。
如果您在开发PHP扩展时需要向PHP用户空间暴露全局变量,则必须通过Zend API在扩展初始化阶段注册这些变量。以下是实现此功能的具体步骤:
ies该方法适用于注册可配置的全局INI变量,变量值可通过php.ini或ini_set()动态修改,并自动绑定到C语言全局变量。
1、在扩展源码的PHP_MINIT_FUNCTION(myext)中声明zend_ini_entry结构体数组,每个元素对应一个INI项。
2、为每个INI项指定名称、默认值、访问权限(如PHP_INI_ALL)、处理回调(可选)及存储地址。
3、调用zend_register_ini_entries(ini_entries, sizeof(ini_entries), module_number)完成注册。
4、在扩展头文件中声明对应的C全局变量(如ZEND_API zend_long myext_counter),确保其地址与INI项的on_modify参数指向一致。
该方法用于在模块启动时向全局作用域($GLOBALS)注入不可配置的常量式变量,变量值由C代码硬编码或运行时计算得出。
1、在PHP_MINIT_FUNCTION中获取全局符号表指针:zend_array *symbol_table = &EG(symbol_table)。
2、构造zval结构体并初始化所需值,例如ZVAL_LONG(&val, 42)或ZVAL_STRING(&val, "hello")。
3、调用zend_hash_str_update(symbol_table, "my_global_var", sizeof("my_global_var") - 1, &val)写入变量。
4、调用Z_TRY_ADDREF(val)防止zval被提前释放(若zval分配在栈上且需长期存在)。
该方法适用于注册模块私有全局结构体中的字段,并使其在PHP脚本中以$myext_config形式访问,需配合TSRMLS机制支持线程安全。
1、在扩展结构体(如myext_globals)中定义目标变量字段,例如zend_long default_timeout。
2、在PHP_GINIT_FUNCTION中初始化该字段,例如myext_globals->default_timeout = 30。
3、在PHP_MINIT_FUNCTION中调用REGISTER_GLOBALS()宏触发全局结构体绑定。
4、在PHP_RINIT_FUNCTION中使用zend_hash_str_update(EG(symbol_table), "myext_config", 12, &config_zv)将结构体内容映射为关联数组。
该方法适合在扩展加载后立即创建仅存在于首次请求生命周期内的全局变量,不依赖INI机制也不写入$GLOBALS。
1、定义静态zval指针变量:static zval *global_flag = NULL。
2、在PHP_MINIT_FUNCTION中调用ALLOC_INIT_ZVAL(global_flag),然后ZVAL_TRUE(global_flag)赋初值。
3、调用zend_hash_str_update(&EG(symbol_table), "is_myext_active", 17, global_flag)完成注册。
4、注意:必须确保global_flag生命周期覆盖整个请求,否则需改用emalloc分配并手动管理内存。
该方法不直接注册变量,而是定义扩展类及其const成员,在PHP用户代码中通过MyExt::VERSION访问,规避全局变量污染问题。
1、在PHP_MINIT_FUNCTION中调用zend_class_entry ce; INIT_CLASS_ENTRY(ce, "MyExt", myext_methods)。
2、调用zend_register_internal_class(&ce)注册类。
3、调用zend_declare_class_constant_string(&ce, "VERSION", 7, "1.2.0")添加字符串常量。
4、调用zend_declare_class_constant_long(&ce, "DEFAULT_RETRY", 13, 5)添加整型常量。
5、此方式注册的常量自动进入全局命名空间,无需额外符号表操作。