类与对像1

类与对像1

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