内容简介:list_destructors 是一个全局静态 HashTable,资源类型注册时,将一个 zval 结构体变量 zv 存放入 list_destructors 的 arData 中,而 zv 的 value.ptr 却指向了 zend_rsrc_list_dtors_entry *lde ,lde中包含的该种资源释放函数指针、持久资源的释放函数指针,资源类型名称,该资源在 hashtable 中的索引依据 (resource_id)等。 --来源于“
-
在
\ext\standard\type.c
中可以找到PHP_FUNCTION(is_array)
所处的位置,大概位于 273 行。 - 在 PHP 中,这个系列的函数,是由很多个,除了它本身之外,还有 is_bool 、 is_countable 、 is_callback 、 is_int 、 is_object 、 is_string 等等
- 在它们之中,大部分的源代码也都是和 is_array 的类似:
PHP_FUNCTION(is_array) { php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_ARRAY); } 复制代码
-
它的定义很简洁,直接调用了
php_is_type
,宏INTERNAL_FUNCTION_PARAM_PASSTHRU
的作用是,将调用 is_array 时的参数,原样传递给 php_is_type 。它的定义如下:
#define INTERNAL_FUNCTION_PARAM_PASSTHRU execute_data, return_value 复制代码
- 函数 php_is_type 的定义如下:
static inline void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type) { zval *arg; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ZVAL(arg) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); if (Z_TYPE_P(arg) == type) { if (type == IS_RESOURCE) { const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg)); if (!type_name) { RETURN_FALSE; } } RETURN_TRUE; } else { RETURN_FALSE; } } 复制代码
- 前面几行是参数解析部分
ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ZVAL(arg) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); 复制代码
-
随后通过
Z_TYPE_P(arg)
获取变量的类型,再让其结果和IS_ARRAY
判等。如果为真,则表示变量是数组,否则不是。 - Z_TYPE_P 的作用很明显,就是获取变量的类型,这个宏展开后如下:
static zend_always_inline zend_uchar zval_get_type(const zval* pz) { return pz->u1.v.type; } 复制代码
-
其中的 pz ,就是 zval 指针, zval 就是 经常提到的
_zval_struct
:
struct _zval_struct { zend_value value; /* 值 */ union { struct { ZEND_ENDIAN_LOHI_3( zend_uchar type, /* 类型 */ zend_uchar type_flags, union { uint16_t call_info; /* call info for EX(This) */ uint16_t extra; /* not further specified */ } u) } v; uint32_t type_info; } u1; union { uint32_t next; /* hash 碰撞时用到的链表 */ uint32_t cache_slot; /* cache slot (for RECV_INIT) */ uint32_t opline_num; /* opline number (for FAST_CALL) */ uint32_t lineno; /* 行号 (ast 节点中) */ uint32_t num_args; /* 参数数量 for EX(This) */ uint32_t fe_pos; /* foreach 时的所在位置 */ uint32_t fe_iter_idx; /* foreach iterator index */ uint32_t access_flags; /* 类时的访问权限标志位 */ uint32_t property_guard; /* single property guard */ uint32_t constant_flags; /* constant flags */ uint32_t extra; /* 保留字段 */ } u2; }; 复制代码
php_is_type if (type == IS_RESOURCE) {
延伸资源类型
const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));
const char *zend_rsrc_list_get_rsrc_type(zend_resource *res) { zend_rsrc_list_dtors_entry *lde; lde = zend_hash_index_find_ptr(&list_destructors, res->type); if (lde) { return lde->type_name; } else { return NULL; } } 复制代码
-
有一个叫做
list_destructors
的静态变量,它的作用如下
list_destructors 是一个全局静态 HashTable,资源类型注册时,将一个 zval 结构体变量 zv 存放入 list_destructors 的 arData 中,而 zv 的 value.ptr 却指向了 zend_rsrc_list_dtors_entry *lde ,lde中包含的该种资源释放函数指针、持久资源的释放函数指针,资源类型名称,该资源在 hashtable 中的索引依据 (resource_id)等。 --来源于“ PHP7 使用资源包裹第三方扩展原理分析 ”
-
也就是说,创建了一个资源类型R1时,就会向
list_destructors
中存入一份 zend_rsrc_list_dtors_entry ,其中包含了该资源R1的一些信息 -
这里的
zend_hash_index_find_ptr
就是找到资源对应的 zend_rsrc_list_dtors_entry ,从而取其中的lde->type_name
- 如果 type 成员是存在的,则说明是资源类型。
总结
-
PHP 中使用
is_*
系列判断类型的函数,大部分都是通过变量底层 zval 中的u1.v.type
来判断类型值 - 如果是资源类型,需要通过 list_destructors 查询对应的资源类型是否存在,如果存在,说明资源句柄是可以正常使用的。
参考资料
- www.jianshu.com/p/5956b4cfc…
- PHP7扩展开发之依赖其他扩展
- PHP7 使用资源包裹第三方扩展原理分析
以上所述就是小编给大家介绍的《PHP 源码 — is_array 函数源码分析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Vue源码: 构造函数入口
- Hashmap源码解析-构造函数
- Hashmap源码解析-扩容函数
- kotlin源码阅读——函数式编程
- Vue 源码中一些util函数
- 深入理解 lambda表达式 与 函数式编程 函数式接口源码解析(二)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Just My Type
Simon Garfield / Profile Books / 2010-10-21 / GBP 14.99
What's your type? Suddenly everyone's obsessed with fonts. Whether you're enraged by Ikea's Verdanagate, want to know what the Beach Boys have in common with easy Jet or why it's okay to like Comic Sa......一起来看看 《Just My Type》 这本书的介绍吧!