php扩展开发-变量

我们在php中用到的变量,在底层的C语言代码里是一个结构体,由四个成员组成typedef struct _zval_struct {
    zvalue_value value;        /* 变量的值,也是一个结构体 */
    zend_uint refcount__gc;    /* 变量的引用计数 typedef unsigned int zend_uint */
    zend_uchar type;           /* 变量的类型 typedef unsigned char zend_uchar */
    zend_uchar is_ref__gc;     /* 是否引用 typedef unsigned char zend_uchar*/
} zval;
typedef union _zvalue_value {
    long lval;                 /* 长整型,存储整数,bool,资源类型 */
    double dval;               /* 浮点型,存储小数 */
    struct {
        char *val;
        int len;               /*  */
    } str;                     /* 字符串,val是字符串指针,len是字符串长度 */
    HashTable *ht;             /* hashtable 即PHP数组 */
    zend_object_value obj;     /* php对象 */
} zvalue_value;

php变量的类型,即zval的type成员,一共有8种

 
类型   zvalue_value中存储的成员 说明
IS_NULL 不存储值 NULL
IS_LONG lval 整型
IS_DOUBLE dval 浮点型
IS_BOOL lval 布尔
IS_RESOURCE lval 资源
IS_STRING str 字符串
IS_ARRAY ht 数组
IS_OBJECT obj 对象

这些类型都是宏定义,在Zend/zend.h中可以查到

1 #define IS_NULL     0
2 #define IS_LONG     1
3 #define IS_DOUBLE   2
4 #define IS_BOOL     3
5 #define IS_ARRAY    4
6 #define IS_OBJECT   5
7 #define IS_STRING   6
8 #define IS_RESOURCE 7

通常我们不会直接使用php变量的成员,例如zval->type或zvalue_value->lval,为了代码的兼容性,zend给我们提供了很多的API方便我们操作变量

宏定义原型 获取变量   描述
zend_uchar Z_TYPE(zval zv) type 返回变量类型
long Z_LVAL(zval zv) value.lval  返回zvalue_value的lval成员
zend_bool Z_BVAL(zval zv) value.lval  返回zvalue_value的lval成员,并且转换成zend_bool类型
double Z_DVAL(zval zv) value.dval  
long Z_RESVAL(zval zv) value.lval 返回zvalue_value的lval成员,此时的type是IS_RESOURCE
char* Z_STRVAL(zval zv) value.str.val 返回字符串的值
int Z_STRLEN(zval zv) value.str.len 返回字符串的长度
HashTable* Z_ARRVAL(zval zv) value.ht 返回hashtable即数组
zend_object_value Z_OBJVAL(zval zv) value.obj returns object value
uint Z_OBJ_HANDLE(zval zv) value.obj.handle returns the object handle for object value
zend_object_handlers* Z_OBJ_HT_P(zval zv) value.obj.handlers returns the handler table for object value
zend_class_entry* Z_OBJCE(zval zv) value.obj returns the class entry for object value
HashTable* Z_OBJPROP(zval zv) value.obj returns the properties of object value
HashTable* Z_OBJPROP(zval zv) value.obj returns the properties of object value
HashTable* Z_OBJDEBUG(zval zv) value.obj if an object has the get_debug_info handler set, it is called, else Z_OBJPROP is called

以上这些API其实就是宏定义,上面列出的每个宏同时都有另外两种类似的定义,以Z_TYPE为例

#define Z_TYPE(zval)        (zval).type         //参数是zval

#define Z_TYPE_P(zval_p)    Z_TYPE(*zval_p)     //参数是zval的指针

#define Z_TYPE_PP(zval_pp)  Z_TYPE(**zval_pp)   //参数是zval的指针的指针

以上这些宏定义,在Zend/zend_operators.h中可以查到

 1 #define Z_LVAL(zval)            (zval).value.lval
 2 #define Z_BVAL(zval)            ((zend_bool)(zval).value.lval)
 3 #define Z_DVAL(zval)            (zval).value.dval
 4 #define Z_STRVAL(zval)          (zval).value.str.val
 5 #define Z_STRLEN(zval)          (zval).value.str.len
 6 #define Z_ARRVAL(zval)          (zval).value.ht
 7 #define Z_AST(zval)         (zval).value.ast
 8 #define Z_OBJVAL(zval)          (zval).value.obj
 9 #define Z_OBJ_HANDLE(zval)      Z_OBJVAL(zval).handle
10 #define Z_OBJ_HT(zval)          Z_OBJVAL(zval).handlers
11 #define Z_OBJCE(zval)           zend_get_class_entry(&(zval) TSRMLS_CC)
12 #define Z_OBJPROP(zval)         Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC)
13 #define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf
14 #define Z_RESVAL(zval)          (zval).value.lval
15 #define Z_OBJDEBUG(zval,is_tmp) (Z_OBJ_HANDLER((zval),get_debug_info)?Z_OBJ_HANDLER((zval),get_debug_info)(&(zval),&is_tmp TSRMLS_CC):(is_tmp=0,Z_OBJ_HANDLER((zval),get_properties)?Z_OBJPROP(zval):NULL))
16
17 #define Z_LVAL_P(zval_p)        Z_LVAL(*zval_p)
18 #define Z_BVAL_P(zval_p)        Z_BVAL(*zval_p)
19 #define Z_DVAL_P(zval_p)        Z_DVAL(*zval_p)
20 #define Z_STRVAL_P(zval_p)      Z_STRVAL(*zval_p)
21 #define Z_STRLEN_P(zval_p)      Z_STRLEN(*zval_p)
22 #define Z_ARRVAL_P(zval_p)      Z_ARRVAL(*zval_p)
23 #define Z_AST_P(zval_p)         Z_AST(*zval_p)
24 #define Z_OBJPROP_P(zval_p)     Z_OBJPROP(*zval_p)
25 #define Z_OBJCE_P(zval_p)       Z_OBJCE(*zval_p)
26 #define Z_RESVAL_P(zval_p)      Z_RESVAL(*zval_p)
27 #define Z_OBJVAL_P(zval_p)      Z_OBJVAL(*zval_p)
28 #define Z_OBJ_HANDLE_P(zval_p)  Z_OBJ_HANDLE(*zval_p)
29 #define Z_OBJ_HT_P(zval_p)      Z_OBJ_HT(*zval_p)
30 #define Z_OBJ_HANDLER_P(zval_p, h)  Z_OBJ_HANDLER(*zval_p, h)
31 #define Z_OBJDEBUG_P(zval_p,is_tmp) Z_OBJDEBUG(*zval_p,is_tmp)
32
33 #define Z_LVAL_PP(zval_pp)      Z_LVAL(**zval_pp)
34 #define Z_BVAL_PP(zval_pp)      Z_BVAL(**zval_pp)
35 #define Z_DVAL_PP(zval_pp)      Z_DVAL(**zval_pp)
36 #define Z_STRVAL_PP(zval_pp)    Z_STRVAL(**zval_pp)
37 #define Z_STRLEN_PP(zval_pp)    Z_STRLEN(**zval_pp)
38 #define Z_ARRVAL_PP(zval_pp)    Z_ARRVAL(**zval_pp)
39 #define Z_AST_PP(zval_p)        Z_AST(**zval_p)
40 #define Z_OBJPROP_PP(zval_pp)   Z_OBJPROP(**zval_pp)
41 #define Z_OBJCE_PP(zval_pp)     Z_OBJCE(**zval_pp)
42 #define Z_RESVAL_PP(zval_pp)    Z_RESVAL(**zval_pp)
43 #define Z_OBJVAL_PP(zval_pp)    Z_OBJVAL(**zval_pp)
44 #define Z_OBJ_HANDLE_PP(zval_p) Z_OBJ_HANDLE(**zval_p)
45 #define Z_OBJ_HT_PP(zval_p)     Z_OBJ_HT(**zval_p)
46 #define Z_OBJ_HANDLER_PP(zval_p, h)     Z_OBJ_HANDLER(**zval_p, h)
47 #define Z_OBJDEBUG_PP(zval_pp,is_tmp)   Z_OBJDEBUG(**zval_pp,is_tmp)

除了获取类型和值之外,还有一些操作跟l变量的refcount__gc和is_ref__gc相关

宏定义原型   描述
zend_uint Z_REFCOUNT(zval zv) 返回refcount__gc的值
zend_uint Z_SET_REFCOUNT(zval zv) 设置zval变量的refcount__gc并返回
zend_uint Z_ADDREF(zval zv) ++zval->refcount__gc并返回
zend_uint Z_DELREF(zval zv) --zval->refcount__gc并返回
zend_bool Z_ISREF(zval zv) 返回zval->is_ref__gc
void Z_UNSET_ISREF(zval zv) set is_ref__gc to 0
void Z_SET_ISREF(zval zv) set is_ref__gc to 1
void Z_SET_ISREF_TO(zval zv, zend_uchar to) set is_ref__gc to to

这些宏定义也同样有*_P或*_PP的版本,可以在Zend/zend.h中查看

 1 #define Z_REFCOUNT_PP(ppz)      Z_REFCOUNT_P(*(ppz))
 2 #define Z_SET_REFCOUNT_PP(ppz, rc)  Z_SET_REFCOUNT_P(*(ppz), rc)
 3 #define Z_ADDREF_PP(ppz)        Z_ADDREF_P(*(ppz))
 4 #define Z_DELREF_PP(ppz)        Z_DELREF_P(*(ppz))
 5 #define Z_ISREF_PP(ppz)         Z_ISREF_P(*(ppz))
 6 #define Z_SET_ISREF_PP(ppz)     Z_SET_ISREF_P(*(ppz))
 7 #define Z_UNSET_ISREF_PP(ppz)       Z_UNSET_ISREF_P(*(ppz))
 8 #define Z_SET_ISREF_TO_PP(ppz, isref)   Z_SET_ISREF_TO_P(*(ppz), isref)
 9
10 #define Z_REFCOUNT_P(pz)        zval_refcount_p(pz)
11 #define Z_SET_REFCOUNT_P(pz, rc)    zval_set_refcount_p(pz, rc)
12 #define Z_ADDREF_P(pz)          zval_addref_p(pz)
13 #define Z_DELREF_P(pz)          zval_delref_p(pz)
14 #define Z_ISREF_P(pz)           zval_isref_p(pz)
15 #define Z_SET_ISREF_P(pz)       zval_set_isref_p(pz)
16 #define Z_UNSET_ISREF_P(pz)     zval_unset_isref_p(pz)
17 #define Z_SET_ISREF_TO_P(pz, isref) zval_set_isref_to_p(pz, isref)
18
19 #define Z_REFCOUNT(z)           Z_REFCOUNT_P(&(z))
20 #define Z_SET_REFCOUNT(z, rc)       Z_SET_REFCOUNT_P(&(z), rc)
21 #define Z_ADDREF(z)         Z_ADDREF_P(&(z))
22 #define Z_DELREF(z)         Z_DELREF_P(&(z))
23 #define Z_ISREF(z)          Z_ISREF_P(&(z))
24 #define Z_SET_ISREF(z)          Z_SET_ISREF_P(&(z))
25 #define Z_UNSET_ISREF(z)        Z_UNSET_ISREF_P(&(z))
26 #define Z_SET_ISREF_TO(z, isref)    Z_SET_ISREF_TO_P(&(z), isref)

我们会在扩展的开发过程中,频繁用到这些zend提供的API操作,你不需要把它记下来,随着开发的进行,你将会慢慢习惯这些API的使用。

时间: 2024-11-08 19:03:45

php扩展开发-变量的相关文章

php扩展开发

本文的环境是windows下开发php版本5.3 1.下载php5.3的源码包和php5.3的二进制包(平时使用的php程序包) 2.下载cygwin,并默认安装在c:\cygwin,因为生成php扩展框架的程序需要cygwin 3.假设php扩展的工作目录为d:\php,解压源码包和二进制包到这个目录 4.cmd命令行在d:\php\ext目录中运行 php ext_skel_win32.php --extname=yourext (如果php.exe程序的路劲未加入系统环境变量则需要自己指定

Chrome扩展开发之三——Chrome扩展中的数据本地存储和下载

目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制和通信方式 3.Chrome扩展开发之三——Chrome扩展中的数据本地存储和下载 4.Chrome扩展开发之四——Gmail API的简单介绍 5.Chrome扩展开发之五——OAuth2的理解 6.Chrome扩展开发之六——GmailAssist核心功能的实现(包括Gmail API的使用中的

Firefox扩展开发

Firefox扩展开发 (插件开发) Extension开发 入门教程 5步走 五步走 首先需要知道什么是"Firefox插件".这里说的"插件"只是一个通俗的说法,其实Firefox这种扩展功能的"插件"包括:扩展extension和插件plugin. {tip:title=Handy Hint} Firefox官方网站的解释是:Extensions are small add-ons that add new functionality to

PHP扩展开发(1):入门

有关PHP扩展开发的文章.博客已经很多了,比较经典的有: TIPI项目(http://www.php-internals.com/,强烈推荐) <Extending and Embedding PHP>(中文翻译见http://www.walu.cc/phpbook/,强烈推荐) <PHP核心技术与最佳实践>一书有一章专门讲PHP扩展开发的,不过版本较老,可供参考. <PHP5权威指南>一书中也有一章专门讲到了PHP的扩展开发. 我准备在此系列博文中总结我有关PHP扩展

【原创】PHP扩展开发进阶

PHP扩展开发进阶 ?作者:wf (360电商技术) 在第一期PHP扩展开发入门中,简单的介绍了PHP的总体架构和执行机制,并具体说明了怎样开发和编译一个主要的PHP扩展,最后在PHP 5.3的环境下结合zend api高速编写了一个静态的PHP扩展. 然而仅仅编译一个PHP扩展是没有实际用途的,它仅仅是一个华丽的外壳,为了使扩展实现更强大的功能,须要在扩展中开发一些有用的功能函数.在这一章中,将会着重介绍PHP内核中变量的实现.在此基础上,才干将须要的功能,使用zend api在PHP扩展中实

php扩展开发-快速上手

系统环境CentOS release 6.5 (Final) PHP版本php-5.6.27 扩展开发需要有php环境及php的源代码,我的PHP安装目录/home/zhangxiaomin/study/php5627/,源码目录/home/zhangxiaomin/study/php-5.6.27, ln -s /home/zhangxiaomin/study/php5627/bin/php /home/zhangxiaomin/bin/php5.6 做一个软连接用php5.6代替/home/

PHP扩展开发教程(总结)

PHP是一种解释型的语言,对于用户而言,我们精心的控制内存意味着easier prototyping和更少的崩溃!当我们深入到内核之后,所有的安全防线都已经被越过,最终还是要依赖于真正有责任心的软件工程师来保证系统的稳定运行. 1.线程安全宏定义 在TSRM/TSRM.h文件中有如下定义 #define TSRMLS_FETCH()       void ***tsrm_ls = (void ***) ts_resource_ex(0, NULL)#define TSRMLS_FETCH_FRO

Chrome浏览器扩展开发系列之十四:本地消息机制Native messagin

Chrome浏览器扩展开发系列之十四:本地消息机制Native messaging 2016-11-24 09:36 114人阅读 评论(0) 收藏 举报  分类: PPAPI(27)  通过将浏览器所在客户端的本地应用注册为Chrome浏览器扩展的"本地消息主机(native messaging host)",Chrome浏览器扩展还可以与客户端本地应用之间收发消息. 客户端的本地应用注册为Chrome浏览器扩展的"本地消息主机"之后,Chrome浏览器会在独立的

openstack 扩展开发最佳实践之计算节点高可用

前言:注意是扩展开发,这个词是我杜撰的,大概意思是指基于openstack的rest api做的一些开发,用于辅助相关功能,而不是直接改动openstack内的代码,怎么修改添加openstack各个组件的代码不在此文章内容内. 首先,千万,千万,千万不要用Openstack提供的SDK,原因如下. 一,SDK的相关文档并不健全. 二,版本不够统一,即兼容的问题. 所以不要使用openstack的SDK而是自己查阅openstack的API文档,通过requests库发http请求要比SDK灵活