要說操作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;
}