1,创建一个扩展
./ext_skel --extname=objects1
2,zend_class_entry结构
struct _zend_class_entry {
char type;
char *name;
zend_uint name_length;
struct _zend_class_entry *parent;
int refcount;
zend_bool constants_updated;
zend_uint ce_flags;
HashTable function_table;
HashTable default_properties;
HashTable properties_info;
HashTable *static_members;
HashTable constants_table;
struct _zend_function_entry *builtin_functions;
union _zend_function *constructor;
union _zend_function *destructor;
union _zend_function *clone;
union _zend_function *_ _get;
union _zend_function *_ _set;
union _zend_function *_ _call;
zend_class_iterator_funcs iterator_funcs;
/* handlers */
zend_object_value (*create_object)(zend_class_entry *class_type TSRMLS_DC);
zend_object_iterator *(*get_iterator)
(zend_class_entry *ce, zval *object TSRMLS_DC);
int (*interface_gets_implemented)
(zend_class_entry *iface, zend_class_entry *class_type TSRMLS_DC);
zend_class_entry **interfaces;
zend_uint num_interfaces;
char *filename;
zend_uint line_start;
zend_uint line_end;
char *doc_comment;
zend_uint doc_comment_len;
};
3,类的定义
static zend_class_entry *hello_ce; //申明类
/*=========================申明类的方法=======================*/
const zend_function_entry hello_methods[] = {
PHP_ME(Hello, __construct, hello___construct_arginfo, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) //构造函数申明 PHP_ME(Hello, __destruct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_DTOR) //析构函数申明
PHP_ME(Hello, __toString, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Hello, updateProperties, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Hello, addProperties, NULL, ZEND_ACC_PUBLIC)
{ NULL, NULL, NULL }
};
/*==========================初始化类=======================================*/
PHP_MINIT_FUNCTION(objects1)
{
/*定义一个temp class*/
zend_class_entry ce;
/*初始化这个class,第二个参数是class name, 第三个参数是class methods*/
INIT_CLASS_ENTRY(ce, "Hello", hello_methods);
/*注册这个class到zend engine*/
/*This function also returns the final class entry, so it can be stored in the global variable declared above*/
hello_ce = zend_register_internal_class(&ce TSRMLS_CC);
return SUCCESS;
}
/*====================定义类的属性======================================*/
zend_declare_property_string(hello_ce, "name", sizeof("name") - 1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_long(hello_ce, "age", sizeof("age") - 1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_string(hello_ce, "last_name", sizeof("last_name") -1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_null(hello_ce, "first_name", sizeof("first_name") -1, ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_bool(hello_ce, "sex", sizeof("sex") -1, 1, ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_double(hello_ce, "score", sizeof("score") -1, 12.50, ZEND_ACC_PUBLIC TSRMLS_CC);
/*====================更新属性值=======================================*/
zval *obj;
obj = getThis();
zend_update_property_string(hello_ce, obj, "name", sizeof("name") -1, "name-update" TSRMLS_CC);//更新属性值, $this->name = name
zend_update_property_long(hello_ce, obj, "age", sizeof("age") -1, 10 TSRMLS_CC); //this->age = age
zend_update_property_string(hello_ce, obj, "last_name", sizeof("last_name") -1, "leon-update" TSRMLS_CC);//this->last_name = "leon"
zend_update_property_null(hello_ce, obj, "first_name", sizeof("first_name") - 1 TSRMLS_CC); //this->first_name = null;
zend_update_property_bool(hello_ce, obj, "sex", sizeof("sex") -1, 0 TSRMLS_CC); //this->sex = true
zend_update_property_double(hello_ce, obj, "score", sizeof("score") -1, 15.50 TSRMLS_CC); //this->score = 12.50
/*==================动态添加属性=====================================*/
zval *obj;
obj = getThis();
/*add zval property*/
zval *arr;
MAKE_STD_ZVAL(arr);
array_init(arr);
add_assoc_string(arr, "e", "hello", 1);
add_index_string(arr, 1, "hello1111", 1);
add_property_zval_ex(obj, "persons", strlen("persons")+1, arr TSRMLS_CC);
Z_DELREF_P(arr);
/*add double property*/
add_property_double(obj, "d", 10.5);
/*add bool property*/
add_property_bool(obj, "b", 1);
/*add string property*/
char *str = "hello str";
add_property_string(obj, "str", str, 1);
/*add long property*/
add_property_long(obj, "l", 12);
/*==========================构造函数=========================*/
ZEND_BEGIN_ARG_INFO(hello___construct_arginfo, 0)
ZEND_ARG_INFO(0, name)
ZEND_ARG_INFO(0, age)
ZEND_END_ARG_INFO()
static PHP_METHOD(Hello, __construct) {
char *name;
int name_len;
long age;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &name, &name_len, &age) == FAILURE) {
return;
}
zval *obj;
obj = getThis();
zend_update_property_stringl(hello_ce, obj, "name", sizeof("name") -1, name, name_len TSRMLS_CC);//更新属性值, $this->name = name
zend_update_property_long(hello_ce, obj, "age", sizeof("age") -1, age TSRMLS_CC); //this->age = age
}
/*=========================析构函数==========================*/
static PHP_METHOD(Hello, __destruct) {
php_printf("call __destruct function...\n");
}
/*========================toString========================*/
static PHP_METHOD(Hello, __toString) {
RETURN_STRING("Hello Class\n", 1);
}
4,类的控制
//fn_flags代表可以在定义方法时使用,zend_property_info.flags代表可以在定义属性时使用,ce_flags代表在定义zend_class_entry时候可用
//ZEND_ACC_CTOR 构造函数掩码 , ZEND_ACC_DTOR 析构函数掩码
//ZEND_ACC_STATIC static函数掩码
//ZEND_ACC_ABSTRACT abstract函数掩码
#define ZEND_ACC_STATIC 0x01 /* fn_flags, zend_property_info.flags */
#define ZEND_ACC_ABSTRACT 0x02 /* fn_flags */
#define ZEND_ACC_FINAL 0x04 /* fn_flags */
#define ZEND_ACC_IMPLEMENTED_ABSTRACT 0x08 /* fn_flags */
#define ZEND_ACC_IMPLICIT_ABSTRACT_CLASS 0x10 /* ce_flags */
#define ZEND_ACC_EXPLICIT_ABSTRACT_CLASS 0x20 /* ce_flags */
#define ZEND_ACC_FINAL_CLASS 0x40 /* ce_flags */
#define ZEND_ACC_INTERFACE 0x80 /* ce_flags */
#define ZEND_ACC_INTERACTIVE 0x10 /* fn_flags */
#define ZEND_ACC_PUBLIC 0x100 /* fn_flags, zend_property_info.flags */
#define ZEND_ACC_PROTECTED 0x200 /* fn_flags, zend_property_info.flags */
#define ZEND_ACC_PRIVATE 0x400 /* fn_flags, zend_property_info.flags */
#define ZEND_ACC_PPP_MASK (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE)
#define ZEND_ACC_CHANGED 0x800 /* fn_flags, zend_property_info.flags */
#define ZEND_ACC_IMPLICIT_PUBLIC 0x1000 /* zend_property_info.flags; unused (1) */
#define ZEND_ACC_CTOR 0x2000 /* fn_flags */
#define ZEND_ACC_DTOR 0x4000 /* fn_flags */
#define ZEND_ACC_CLONE 0x8000 /* fn_flags */
#define ZEND_ACC_ALLOW_STATIC 0x10000 /* fn_flags */
#define ZEND_ACC_SHADOW 0x20000 /* fn_flags */
#define ZEND_ACC_DEPRECATED 0x40000 /* fn_flags */
#define ZEND_ACC_CLOSURE 0x100000 /* fn_flags */
#define ZEND_ACC_CALL_VIA_HANDLER 0x200000 /* fn_flags */
5,宏
#define INIT_CLASS_ENTRY(class_container, class_name, functions) INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, NULL, NULL, NULL)
#define INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, handle_fcall, handle_propget, handle_propset) INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, sizeof(class_name)-1, functions, handle_fcall, handle_propget, handle_propset, NULL, NULL)
define INIT_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions) INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions, NULL, NULL, NULL, NULL, NULL)
define INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) {
const char *cl_name = class_name;
int _len = class_name_len;
class_container.name = zend_new_interned_string(cl_name, _len+1, 0 TSRMLS_CC);
if (class_container.name == cl_name) {
class_container.name = zend_strndup(cl_name, _len);
}
class_container.name_length = _len;
INIT_CLASS_ENTRY_INIT_METHODS(class_container, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \
}
#define INIT_CLASS_ENTRY_INIT_METHODS(class_container, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) {
class_container.constructor = NULL;
class_container.destructor = NULL;
class_container.clone = NULL;
class_container.serialize = NULL;
class_container.unserialize = NULL;
class_container.create_object = NULL;
class_container.interface_gets_implemented = NULL;
class_container.get_static_method = NULL;
class_container.__call = handle_fcall;
class_container.__callstatic = NULL;
class_container.__tostring = NULL;
class_container.__get = handle_propget;
class_container.__set = handle_propset;
class_container.__unset = handle_propunset;
class_container.__isset = handle_propisset;
class_container.serialize_func = NULL;
class_container.unserialize_func = NULL;
class_container.serialize = NULL;
class_container.unserialize = NULL;
class_container.parent = NULL;
class_container.num_interfaces = 0;
class_container.traits = NULL;
class_container.num_traits = 0;
class_container.trait_aliases = NULL;
class_container.trait_precedences = NULL;
class_container.interfaces = NULL;
class_container.get_iterator = NULL;
class_container.iterator_funcs.funcs = NULL;
class_container.info.internal.module = NULL;
class_container.info.internal.builtin_functions = functions;
}