类与对像3(object handlers)

类与对像3(object handlers)

1,创建一个扩展

./ext_skel --extname=objects3

2,object handlers定义

typedef zval *(*zend_object_read_property_t)(zval *object, zval *member, int type, const struct _zend_literal *key TSRMLS_DC);
typedef zval *(*zend_object_read_dimension_t)(zval *object, zval *offset, int type TSRMLS_DC);
typedef void (*zend_object_write_property_t)(zval *object, zval *member, zval *value, const struct _zend_literal *key TSRMLS_DC);
typedef void (*zend_object_write_dimension_t)(zval *object, zval *offset, zval *value TSRMLS_DC);
typedef zval **(*zend_object_get_property_ptr_ptr_t)(zval *object, zval *member, int type, const struct _zend_literal *key TSRMLS_DC);
typedef void (*zend_object_set_t)(zval **object, zval *value TSRMLS_DC);
typedef zval* (*zend_object_get_t)(zval *object TSRMLS_DC);
typedef int (*zend_object_has_property_t)(zval *object, zval *member, int has_set_exists, const struct _zend_literal *key TSRMLS_DC);
typedef int (*zend_object_has_dimension_t)(zval *object, zval *member, int check_empty TSRMLS_DC);
typedef void (*zend_object_unset_property_t)(zval *object, zval *member, const struct _zend_literal *key TSRMLS_DC);
typedef void (*zend_object_unset_dimension_t)(zval *object, zval *offset TSRMLS_DC);
typedef HashTable *(*zend_object_get_properties_t)(zval *object TSRMLS_DC);
typedef HashTable *(*zend_object_get_debug_info_t)(zval *object, int *is_temp TSRMLS_DC);

typedef int (*zend_object_call_method_t)(const char *method, INTERNAL_FUNCTION_PARAMETERS);
typedef union _zend_function *(*zend_object_get_method_t)(zval **object_ptr, char *method, int method_len, const struct _zend_literal *key TSRMLS_DC);
typedef union _zend_function *(*zend_object_get_constructor_t)(zval *object TSRMLS_DC);

typedef void (*zend_object_add_ref_t)(zval *object TSRMLS_DC);
typedef void (*zend_object_del_ref_t)(zval *object TSRMLS_DC);
typedef void (*zend_object_delete_obj_t)(zval *object TSRMLS_DC);
typedef zend_object_value (*zend_object_clone_obj_t)(zval *object TSRMLS_DC);

typedef zend_class_entry *(*zend_object_get_class_entry_t)(const zval *object TSRMLS_DC);
typedef int (*zend_object_get_class_name_t)(const zval *object, const char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC);
typedef int (*zend_object_compare_t)(zval *object1, zval *object2 TSRMLS_DC);

typedef int (*zend_object_cast_t)(zval *readobj, zval *retval, int type TSRMLS_DC);

typedef int (*zend_object_count_elements_t)(zval *object, long *count TSRMLS_DC);

typedef int (*zend_object_get_closure_t)(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC);

typedef HashTable *(*zend_object_get_gc_t)(zval *object, zval ***table, int *n TSRMLS_DC);

#所以后缀带_dimension的都是以$obj[foo]的方式访问对像,其他的是以 $obj->foo访问对像
struct _zend_object_handlers {
    /* general object functions */
    zend_object_add_ref_t                   add_ref;    #添加引用
    zend_object_del_ref_t                   del_ref;    #删除引用
    zend_object_clone_obj_t                 clone_obj;  #克隆对像
    /* individual object functions */
    zend_object_read_property_t             read_property; #$obj->foo方式读取属性值
    zend_object_write_property_t            write_property; #$obj->foo方式写入属性值
    zend_object_read_dimension_t            read_dimension; #$obj[foo]方式读取属性值
    zend_object_write_dimension_t           write_dimension; #$obj[foo]方式写入属性值
    zend_object_get_property_ptr_ptr_t      get_property_ptr_ptr;
    zend_object_get_t                       get;
    zend_object_set_t                       set;
    zend_object_has_property_t              has_property;
    zend_object_unset_property_t            unset_property;
    zend_object_has_dimension_t             has_dimension;
    zend_object_unset_dimension_t           unset_dimension;
    zend_object_get_properties_t            get_properties;
    zend_object_get_method_t                get_method;
    zend_object_call_method_t               call_method;
    zend_object_get_constructor_t           get_constructor;
    zend_object_get_class_entry_t           get_class_entry;
    zend_object_get_class_name_t            get_class_name;
    zend_object_compare_t                   compare_objects;
    zend_object_cast_t                      cast_object;
    zend_object_count_elements_t            count_elements;
    zend_object_get_debug_info_t            get_debug_info;
    zend_object_get_closure_t               get_closure;
    zend_object_get_gc_t                    get_gc;
};

extern ZEND_API zend_object_handlers std_object_handlers;

3,添加object handlers

1,定义 handlers

static zend_object_handlers hello_handlers;

2,初始化 handlers

memcpy(&hello_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
hello_handlers.clone_obj = hello_clone;
//hello_handlers.get = hello_get;
hello_handlers.count_elements = hello_count_elements;

3,设置 object 的 handlers

hello_object *objval = emalloc(sizeof(hello_object));
memset(objval, 0, sizeof(hello_object));

zend_object_value retval;
zend_object_std_init(&(objval->obj), ce TSRMLS_CC);

retval.handle = zend_objects_store_put(objval , 
                                        NULL, 
                                        (zend_objects_free_object_storage_t)hello_dtor, 
                                        NULL TSRMLS_CC);
retval.handlers = &hello_handlers;

4,实现handlers

static int hello_count_elements(zval *object, long *count TSRMLS_DC) {
    zend_object_handlers *zh = zend_get_std_object_handlers();
    php_printf("count: %ld\n", *count);
    *count = 5;
    return SUCCESS;
}

4,测试php

$obj = new Hello("leon", 32);
echo "obj count:" . count($obj)."\n"; //结果为5