【php7扩展开发二】全局变量
使用C語言開發(fā)程序時(shí)經(jīng)常會(huì)使用全局變量進(jìn)行數(shù)據(jù)存儲(chǔ),這就涉及前面已經(jīng)介紹過的一個(gè)問題:線程安全,PHP設(shè)計(jì)了TSRM(即:線程安全資源管理器)用于解決這個(gè)問題,內(nèi)核中頻繁使用到的EG、CG等都是根據(jù)是否開啟ZTS封裝的宏,同樣的,在擴(kuò)展中也需要必須按照TSRM的規(guī)范定義全局變量,除非你的擴(kuò)展不支持多線程的環(huán)境。
PHP為擴(kuò)展的全局變量提供了一種存儲(chǔ)方式:每個(gè)擴(kuò)展將自己所有的全局變量統(tǒng)一定義在一個(gè)結(jié)構(gòu)體中,然后將這個(gè)結(jié)構(gòu)體注冊(cè)到TSRM中,這樣擴(kuò)展就可以像使用EG、CG那樣訪問這個(gè)結(jié)構(gòu)體。
這個(gè)結(jié)構(gòu)體的定義通過ZEND_BEGIN_MODULE_GLOBALS(extension_name),ZEND_END_MODULE_GLOBALS(extension_name)兩個(gè)宏完成,這兩個(gè)宏必須成對(duì)出現(xiàn),中間定義擴(kuò)展需要的全局變量即可。
ZEND_BEGIN_MODULE_GLOBALS(hello)zend_long greeting; ZEND_END_MODULE_GLOBALS(hello)展開后實(shí)際就是個(gè)普通的struct:
typedef struct _zend_hello_globals {zend_long greeting; } zend_hello_globals;接著創(chuàng)建一個(gè)此結(jié)構(gòu)體的全局變量,這時(shí)候就會(huì)涉及ZTS了,如果未開啟線程安全直接創(chuàng)建普通的全局變量即可,如果開啟線程安全了則需要向TSRM注冊(cè),得到一個(gè)唯一的資源id,這個(gè)操作也由專門的宏來完成:ZEND_DECLARE_MODULE_GLOBALS(extension_name),展開后:
//ZTS: 此時(shí)只是定義資源id,并沒有向TSRM注冊(cè) ts_rsrc_id hello_globals_id;//非ZTS zend_hello_globals hello_global;最后需要定義一個(gè)像EG、CG那樣的宏用于訪問擴(kuò)展的全局資源結(jié)構(gòu)體,這一步使用ZEND_MODULE_GLOBALS_ACCESSOR()宏完成:
#define HELLO_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(hello, v)
看起來是不是跟EG、CG的定義非常像?這個(gè)宏展開后:
//ZTS #define hello_G(v) ZEND_TSRMG(hello_globals_id, zend_hello_globals *, v) //非ZTS #define hello_G(v) (hello_globals.v)接下來就可以在擴(kuò)展中通過:MYTEST_G(greeting)、對(duì)結(jié)構(gòu)體成員進(jìn)行讀寫了。下面來看一個(gè)demo:
//php_hello.h #define HELLO_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(hello, v)ZEND_BEGIN_MODULE_GLOBALS(hello)zend_long greeting; ZEND_END_MODULE_GLOBALS(hello)//hello.c ZEND_DECLARE_MODULE_GLOBALS(hello)PHP_FUNCTION(hello_change_ini) {HELLO_G(greeting) ++; }PHP_FUNCTION(hello_ini) {RETURN_LONG(HELLO_G(greeting)); }//index.php <?phpecho hello_ini(); //0hello_change_ini();echo "<br>";echo hello_ini(); //1 >?
總結(jié)
以上是生活随笔為你收集整理的【php7扩展开发二】全局变量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【php内核与扩展开发系列】PHP生命周
- 下一篇: 【php7扩展开发一】注册一个内部函数h