php扩展开发-变量

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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的使用。


以上是关于php扩展开发-变量的主要内容,如果未能解决你的问题,请参考以下文章

PHP必用代码片段

PHP项目开发经验整理

如何从C扩展名(PHP源)读取和写入PHP超全局变量? [处于保留状态]

超级有用的9个PHP代码片段

超实用的php代码片段

php 变量片段