我们在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