php对象的实现

时间:2023-03-10 04:13:05
php对象的实现

1.对象的数据结构非常简单

typedef struct _zend_object     zend_object;

struct _zend_object {
zend_refcounted_h gc; //引用计数
uint32_t handle;
zend_class_entry *ce; //所属类
const zend_object_handlers *handlers; //对象操作处理函数
HashTable *properties;
zval properties_table[]; //普通属性值数组
};

handle: 一次request期间对象的编号,每个对象都有一个唯一的编号,与创建先后顺序有关,主要在垃圾回收时用

ce: 所属类的zend_class_entry

handlers: 这个保存的对象相关操作的一些函数指针,比如成员属性的读写、成员方法的获取、对象的销毁/克隆等等,这些操作接口都有默认的函数

struct _zend_object_handlers {
int offset;
zend_object_free_obj_t free_obj; //释放对象
zend_object_dtor_obj_t dtor_obj; //销毁对象
zend_object_clone_obj_t clone_obj;//复制对象 zend_object_read_property_t read_property; //读取成员属性
zend_object_write_property_t write_property;//修改成员属性
...
} //默认值处理handler
ZEND_API zend_object_handlers std_object_handlers = {
,
zend_object_std_dtor, /* free_obj */
zend_objects_destroy_object, /* dtor_obj */
zend_objects_clone_obj, /* clone_obj */
zend_std_read_property, /* read_property */
zend_std_write_property, /* write_property */
zend_std_read_dimension, /* read_dimension */
zend_std_write_dimension, /* write_dimension */
zend_std_get_property_ptr_ptr, /* get_property_ptr_ptr */
NULL, /* get */
NULL, /* set */
zend_std_has_property, /* has_property */
zend_std_unset_property, /* unset_property */
zend_std_has_dimension, /* has_dimension */
zend_std_unset_dimension, /* unset_dimension */
zend_std_get_properties, /* get_properties */
zend_std_get_method, /* get_method */
NULL, /* call_method */
zend_std_get_constructor, /* get_constructor */
zend_std_object_get_class_name, /* get_class_name */
zend_std_compare_objects, /* compare_objects */
zend_std_cast_object_tostring, /* cast_object */
NULL, /* count_elements */
zend_std_get_debug_info, /* get_debug_info */
zend_std_get_closure, /* get_closure */
zend_std_get_gc, /* get_gc */
NULL, /* do_operation */
NULL, /* compare */
}

properties: 普通成员属性哈希表,对象创建之初这个值为NULL

properties_table: 成员属性数组,它是一个数组,zend_object是个变长结构体,分配时会根据非静态属性的数量确定其大小

普通成员属性的查找比较容易理解,首先是从zend_class的属性信息哈希表中找到zend_property_info,并判断其可见性(public、private、protected),如果可以访问则直接根据属性的offset在zend_object.properties_table数组中取到属性值