后,为了使自定义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宏声名正在接收上下文。
下面是前一例子的重写,利用了参数传递上下文。
复制代码 代码如下:
void myfunc(TSRMLS_D){
MYFILE_G(myglobal) = 2;
}
PHP_FUNCTION(my_php_function)
{
…
myfunc(TSRMLS_C);
…
}
~
总 结
现在,你已经学到了足够的东西来创建自己的扩展。本章讲述了一些重要的基础来编写和理解PHP扩展。Zend引擎提供的扩展API相当丰富,使你能够开发面向对象的扩展。几乎没有文档谈几许多高级特性。当然,依靠本章所学的基础知识,你可以通过浏览现有的原码学到很多。
更多关于信息可以在PHP手册的扩展PHP章节http://www.php.net/manual/en/zend.php中找到。另外,你也可以考虑加入PHP开发者邮件列表internals@ lists.php.net,该邮件列表围绕开发PHP 本身。你还可以查看一下新的扩展生成工具——PECL_Gen(http://pear.php.net/package/PECL_Gen),这个工具正在开发之中,比起本章使用的ext_skel有更多的特性。
此外你还可以关注风雪之隅, 会有更多相关知识更新.
词汇表
binary safe | 二进制安全 |
context | 上下文 |
extensions | 扩展 |
entry | 条目 |
skeleton | 骨架 |
Thread-Safe Resource Manager TSRM | 线程安全资源管理器 |
可参考译者写的
译者:可以使用phpcli
程序在控制台里执行php文件。
译者:可以查看到生成的FETCH_RESOURCE()宏参数是一些''???''。