本文基于的PHP版本为7.3.12
我们在开发PHP
扩展的时候,经常会要去读取对象的属性,一般来说就是使用zend_read_property
这个函数来完成。这个函数的原型如下:
1 | ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_bool silent, zval *rv); |
这个函数的返回值很容易理解,就是这个属性对应的value
值。那么,最后一个参数zval *rv
有什么用呢?
这个参数是给动态属性来用的。我们知道,当访问一个PHP
对象的动态属性的时候,是会去调用这个对象的__get
魔术方法。而动态属性它的内存是不在zend_object
上面的,它是通过__get
魔术方法来得到的。而普通的属性它的内存是在zend_object
上面的,所以,当我们去访问普通的属性的时候,可以直接返回一个zval
。
既然访问动态属性是通过调用__get
魔术方法来实现的,那么,类似于zend_call_method
一样,我们需要去设置zend_fcall_info::retval
。当函数调用结束的时候,返回值就会存放在这个zval
中。这样,我们就可以取到动态属性的值了。
核心的代码如下:
1 | static void zend_std_call_getter(zend_object *zobj, zend_string *prop_name, zval *retval) /* {{{ */ |
当访问PHP
对象的动态属性的时候,就会去调用这个函数。而这个函数的retval
就是我们zend_read_property
的rv
参数。