zend_object 对象的新建和操作

要说操作zend_object 先要熟悉下怎么在扩展中定义类 zend_class_entry, 可以读读这篇文章了解下如何在扩展中定义类

类定义

简要说下定义类的关键点

zend_class_entry *myclass_ce;

static zend_function_entry myclass_method[] = {
    { NULL, NULL, NULL }
};

PHP_MINIT_FUNCTION(academy_sample_class)
{
    zend_class_entry ce;

    //myclass是这个类的名称
    INIT_CLASS_ENTRY(ce, "myclass", myclass_method);  
//这里定义了类名和方法,初始化zend_class_entry这个结构体
    myclass_ce = zend_register_internal_class(&ce TSRMLS_CC);
 //这里是把这个zend_class_entry 这个初始化的结构体放到CG(class_table)这个编译时全局变量hash table 中 
    return SUCCESS;
}

我们上面还定义了一个 myclass_ce 指针,它是干什么用的呢?当我们在扩展中对这个类进行操作,比如生成实例的时候,会使用到它,它的作用就类似于打开文件的操作句柄。


/*************zend_API.C*****************/
ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry) /* {{{ */
{
    return do_register_internal_class(orig_class_entry, 0);
}

/*************zend_API.C*****************/
static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, uint32_t ce_flags) /* {{{ */
{
    zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
    zend_string *lowercase_name = zend_string_alloc(ZSTR_LEN(orig_class_entry->name), 1);
    *class_entry = *orig_class_entry;

    class_entry->type = ZEND_INTERNAL_CLASS;
    zend_initialize_class_data(class_entry, 0);
    class_entry->ce_flags = ce_flags | ZEND_ACC_CONSTANTS_UPDATED;
    class_entry->info.internal.module = EG(current_module);

    if (class_entry->info.internal.builtin_functions) {
        zend_register_functions(class_entry, class_entry->info.internal.builtin_functions, &class_entry->function_table, MODULE_PERSISTENT);
    }

    zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ZSTR_VAL(orig_class_entry->name), ZSTR_LEN(class_entry->name));
    lowercase_name = zend_new_interned_string(lowercase_name);
    zend_hash_update_ptr(CG(class_table), lowercase_name, class_entry);//把 zend_class_entry 注册到CG(class_table) hash table 中
    zend_string_release(lowercase_name);
    return class_entry;
}

对象创建销毁

/**********zend_objects.h************/

ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce);  //创建和初始化对象
ZEND_API void zend_object_std_dtor(zend_object *object);
ZEND_API zend_object *zend_objects_new(zend_class_entry *ce); //新建对象
ZEND_API void zend_objects_destroy_object(zend_object *object);
ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *old_object);
ZEND_API zend_object *zend_objects_clone_obj(zval *object);

对象属性操作

/**********zend_API.c************/

//更新属性
ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zval *value);
ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value);
ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, size_t name_length);
ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value);
ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value);
ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, size_t name_length, double value);
ZEND_API void zend_update_property_str(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_string *value);
ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value);
ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value, size_t value_length);

//更新静态属性
ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value);
ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, size_t name_length);
ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, size_t name_length, zend_long value);
ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, size_t name_length, zend_long value);
ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, size_t name_length, double value);
ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, size_t name_length, const char *value);
ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, size_t name_length, const char *value, size_t value_length);

读对象属性和静态属性
ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zend_bool silent, zval *rv);
ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_bool silent, zval *rv);
ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, zend_bool silent);

//声明对象常量和update常量值
ZEND_API int zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int access_type, zend_string *doc_comment);
ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value);
ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length);
ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value);
ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value);
ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value);
ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length);
ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value);

ZEND_API int zend_update_class_constants(zend_class_entry *class_type);

对象方法调用

//Zend/zend_interfaces.h

ZEND_API zval* zend_call_method(zval *object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval, int param_count, zval* arg1, zval* arg2);

zend_call_method_with_0_params(obj, obj_ce, fn_proxy, function_name, retval) 
zend_call_method_with_1_params(obj, obj_ce, fn_proxy, function_name, retval, arg1) 
zend_call_method_with_2_params(obj, obj_ce, fn_proxy, function_name, retval, arg1, arg2) 

这里有个问题,调用函数方法貌似最多传2个参数,那么多余两个参数的方法调用要怎么办呢?
这个需要自己去封装 zend_call_function() , 可以参考这篇文章https://www.cnblogs.com/djhull/p/5359634.html

类的方法中操作对象demo

PHP_METHOD(Person, __construct) {
 php_printf("__construct called.");
}

PHP_METHOD(Person, __destruct) {
 php_printf("__destruct called.
"); } PHP_METHOD(Person, getName) { zval *self, *name; self = getThis(); //获取当前对象, 相当于 this指针 name = zend_read_property(Z_OBJCE_P(self), self, ZEND_STRL("_name"), 0 TSRMLS_CC); //获取对象属性值 RETURN_STRING(Z_STRVAL_P(name), 0); } PHP_METHOD(Person, setName) { char *arg = NULL; int arg_len; zval *value, *self; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { WRONG_PARAM_COUNT; } self = getThis(); MAKE_STD_ZVAL(value); ZVAL_STRINGL(value, arg, arg_len, 0); SEPARATE_ZVAL_TO_MAKE_IS_REF(&value); zend_update_property(Z_OBJCE_P(self), self, ZEND_STRL("_name"), value TSRMLS_CC); //更新对象属性 RETURN_TRUE; }

你可能感兴趣的:(zend_object 对象的新建和操作)