php扩展zval,PHP扩展开发(7):zval结构

在前面的文章多次提到了zval结构,其实所有用户定义的变量在PHP中都是用zval类型来表示的,当我门

使用zend_parse_parameters函数解析参数时,Zend引擎会根据相应的数据类型进行类型转换,而由于PHP中的数组、对象和资源类

型,在C语言中没有对应的类型,所以无法进行类型转换,它们都使用zval表示,先看一下zval结构定义:

typedefpval zval;

typedef struct_zval_struct zval;

struct_zval_struct {

/* Variable information */zvalue_value value; /* value */unsigned chartype; /* active type */unsigned charis_ref;

shortrefcount;

};

zval结构的定义使用了C语言中的联合类型,各个字段说明如下:

value    变量内容的联合,参见“表3.6 Zend zvalue_value 结构”

type    变量的类型。“表3.7 Zend 变量类型”给出了一个完整的变量类型列表

is_ref    0 表示这个变量还不是一个引用。1 表示这个变量还有被别的变量所引用

refcount    表示这个变量是否仍然有效。每增加一个对这个变量的引用,这个数值就增加 1。反之,每失去一个对这个变量的引用,该值就会减1。当引用计数减为0的时候,就说明已经不存在对这个变量的引用了,于是这个变量就会自动释放

变量类型定义:

IS_NULL    表示是一个空值 NULL

IS_LONG    是一个(长)整数

IS_DOUBLE    是一个双精度的浮点数

IS_STRING    是一个字符串

IS_ARRAY    是一个数组

IS_OBJECT    是一个对象

IS_BOOL    是一个布尔值

IS_RESOURCE    是一个资源(关于资源的讨论,我们以后会在适当的时候讨论到它)

IS_STRING    是一个常量

zvalue_value结构定义:

typedef union_zvalue_value {

longlval; /* long value */doubledval; /* double value */struct{

char*val;

intlen;

} str;

HashTable *ht; /* hash table value */struct{

zend_class_entry *ce;

HashTable *properties;

} obj;

} zvalue_value;

zvalue_value结构的说明如下:

lval    如果变量类型为 IS_LONG、IS_BOOLEAN 或 IS_RESOURCE 就用这个属性值

dval    如果变量类型为 IS_DOUBLE 就用这个属性值

str    如果变量类型为 IS_STRING 就访问这个属性值。它的字段 len 表示这个字符串的长度,字段 val 则指向该字符串。由于 Zend 使用的是 C 风格的字符串,因此字符串的长度就必须把字符串末尾的结束符 0×00 也计算在内

ht    如果变量类型为数组,那这个 ht 就指向数组的哈希表入口

obj    如果变量类型为 IS_OBJECT 就用这个属性值

给定一个具体的zval,可用三个便利的宏中的一个测试它的类型:Z_TYPE(zval)、Z_TYPE_P(zval*)或Z_TYPE_PP(zval**)。三者之间仅有的功能上的区别在于传入的变量所期望的间接的级别。如下面的示例:

PHP_FUNCTION(hello_dump)

{

zval *uservar;

if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z",

&uservar) == FAILURE) {

RETURN_NULL();

}

switch(Z_TYPE_P(uservar)) {

caseIS_NULL:

php_printf("NULL\n");

break;

caseIS_BOOL:

php_printf("Boolean: %s\n", Z_LVAL_P(uservar) ? "TRUE": "FALSE");

break;

caseIS_LONG:

php_printf("Long: %ld\n", Z_LVAL_P(uservar));

break;

caseIS_DOUBLE:

php_printf("Double: %f\n", Z_DVAL_P(uservar));

break;

caseIS_STRING:

php_printf("String: ");

PHPWRITE(Z_STRVAL_P(uservar), Z_STRLEN_P(uservar));

php_printf("\n");

break;

caseIS_RESOURCE:

php_printf("Resource\n");

break;

caseIS_ARRAY:

php_printf("Array\n");

break;

caseIS_OBJECT:

php_printf("Object\n");

break;

default:

php_printf("Unknown\n");

}RETURN_TRUE;

}

编写一个简单的测试脚本:

hello_dump(1234);

echo '
';

hello_dump('terrylee');

echo '
';

hello_dump(array('foo', 'bar'));

?>

运行后效果如下:

image.axd?picture=011.png

在PHP扩展中对于用户传过来的参数,本质上都是一个zval结构,我们需要调用一些转换函数进行强制类型转换(zend_parse_parameters函数会对基本类型做转换),Zend引擎提供了convert_to_xxx系列函数帮助我们进行类型转换:

convert_to_boolean_ex()

强制转换为布尔类型。若原来是布尔值则保留,不做改动。长整型值0、双精度型值0.0、空字符串或字符串‘0’还有空值 NULL 都将被转换为

FALSE(本质上是一个整数 0)。数组和对象若为空则转换为 FALSE,否则转为 TRUE。除此之外的所有值均转换为

TRUE(本质上是一个整数 1)。

convert_to_long_ex()

强制转换为长整型,这也是默认的整数类型。如果原来是空值NULL、布尔型、资源当然还有长整型,则其值保持不变(因为本质上都是整数

0)。双精度型则被简单取整。包含有一个整数的字符串将会被转换为对应的整数,否则转换为 0。空的数组和对象将被转换为 0,否则将被转换为 1。

convert_to_double_ex()

强制转换为一个双精度型,这是默认的浮点数类型。如果原来是空值 NULL

、布尔值、资源和双精度型则其值保持不变(只变一下变量类型)。包含有一个数字的字符串将被转换成相应的数字,否则被转换为

0.0。空的数组和对象将被转换为 0.0,否则将被转换为 1.0。

convert_to_string_ex()

强制转换为数组。若原来就是一数组则不作改动。对象将被转换为一个以其属性为键名,以其属性值为键值的数组。(方法强制转换为字符串。空值 NULL

将被转换为空字符串。布尔值 TRUE 将被转换为 ‘1’,FALSE

则被转为一个空字符串。长整型和双精度型会被分别转换为对应的字符串,数组将会被转换为字符串‘Array’,而对象则被转换为字符串‘Object’。

convert_to_array_ex(value)

强制转换为数组。若原来就是一数组则不作改动。对象将被转换为一个以其属性为键名,以其属性值为键值的数组。(方法将会被转化为一个‘scalar’键,

键值为方法名)空值 NULL 将被转换为一个空数组。除此之外的所有值都将被转换为仅有一个元素(下标为 0)的数组,并且该元素即为该值。

convert_to_object_ex(value)    强制转换为对象。若原来就是对象则不作改动。空值 NULL 将被转换为一个空对象。数组将被转换为一个以其键名为属性,键值为其属性值的对象。其他类型则被转换为一个具有‘scalar’属性的对象,‘scalar’属性的值即为该值本身。

convert_to_null_ex(value)    强制转换为空值 NULL。

关于zval结构的介绍就到这里了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值