zend_object 對象的新建和操作

要說操作zend_object 先要熟悉下怎么在擴(kuò)展中定義類 zend_class_entry, 可以讀讀這篇文章了解下如何在擴(kuò)展中定義類

類定義

簡要說下定義類的關(guān)鍵點(diǎn)

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是這個(gè)類的名稱
    INIT_CLASS_ENTRY(ce, "myclass", myclass_method);  
//這里定義了類名和方法,初始化zend_class_entry這個(gè)結(jié)構(gòu)體
    myclass_ce = zend_register_internal_class(&ce TSRMLS_CC);
 //這里是把這個(gè)zend_class_entry 這個(gè)初始化的結(jié)構(gòu)體放到CG(class_table)這個(gè)編譯時(shí)全局變量hash table 中 
    return SUCCESS;
}

我們上面還定義了一個(gè) myclass_ce 指針,它是干什么用的呢?當(dāng)我們在擴(kuò)展中對這個(gè)類進(jìn)行操作,比如生成實(shí)例的時(shí)候,會(huì)使用到它,它的作用就類似于打開文件的操作句柄。


/*************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;
}

對象創(chuàng)建銷毀

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

ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce);  //創(chuàng)建和初始化對象
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);

//更新靜態(tài)屬性
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);

讀對象屬性和靜態(tài)屬性
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);

對象方法調(diào)用

//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) 

這里有個(gè)問題,調(diào)用函數(shù)方法貌似最多傳2個(gè)參數(shù),那么多余兩個(gè)參數(shù)的方法調(diào)用要怎么辦呢?
這個(gè)需要自己去封裝 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.<br/>");
}

PHP_METHOD(Person, getName) {
 zval *self, *name;
 self = getThis();  //獲取當(dāng)前對象, 相當(dāng)于 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;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容