zoukankan      html  css  js  c++  java
  • php扩展开发-面向对象

    在zval变量里IS_OBJECT类型使用zend_object_value来保存变量的,我们看一下他的具体结果。

    typedef struct _zend_object_value {
        zend_object_handle handle;
        const zend_object_handlers *handlers;
    } zend_object_value;

    在扩展中创建一个我们自己的类

    zend_class_entry *myext_class_ce;//保存我们创建的对象实例
    
    static zend_function_entry myext_class_method[] = {//函数的属性和方法都在这里定义
        {NULL, NULL, NULL}//固定语法
    };
    
    //在MINIT函数里
    PHP_MINIT_FUNCTION(myext)
    {
        zend_class_entry tmp_myext_class_ce;//临时变量
        INIT_CLASS_ENTRY(tmp_myext_class_ce,"myext_example_class",myext_class_method);//临时变量,类名称,类属性和方法
        myext_class_ce = zend_register_internal_class(&tmp_myext_class_ce TSRMLS_CC);//在内核中注册我们的类
    }

    /*

    $class = new myext_example_class();

      var_dump($class);

      object(myext_example_class)#6 (0) {
      }

      */

    创建类的第一个函数

    ZEND_METHOD(myext_example_class,hello);
    
    //ZEND_ME为方法注册,每个方法使用一个ZEND_ME
    //参数说明
    //1,类名称
    //2,方法名称
    //3,参数,跟普通函数的一样,也是ZEND_END_ARG_INFO
    //4,修饰方法或属性,后面会专门讲到
    static zend_function_entry myext_class_method[] = {
        ZEND_ME(myext_example_class,hello,NULL,ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}//固定语法
    };
    
    //函数定义,参数说明:
    //类名称
    //类方法名称
    ZEND_METHOD(myext_example_class,hello){
        php_printf("hello");
    }

    创建一个构造函数__construct()

    ZEND_METHOD(myext_example_class,__construct);
    
    //创建构造方法同普通方法基本一样,唯一的差别在于第四个参数,ZEND_ACC_CTOR,表示它是构造方法
    static zend_function_entry myext_class_method[] = { ZEND_ME(myext_example_class,hello,NULL,ZEND_ACC_PUBLIC) ZEND_ME(myext_example_class,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) {NULL, NULL, NULL}//固定语法 }; ZEND_METHOD(myext_example_class,__construct){ php_printf("我是__construct函数"); }

    现在来看一下修饰方法和属性的常量,通过他们可以定义方法的访问权限,是否是抽奖函数,是否是FINAL属性等等

    下面详细的罗列出了所有常量,fn_flags代表可以在定义方法时使用,zend_property_info.flags代表可以在定义属性时使用,ce_flags代表在定义zend_class_entry时候可用。当需要用到多个常量的时候,我们可以采用或运算的形式,在定义构造函数的时候,我们已经遇到了,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR

    #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 */

    现在我们为这个类增加一些属性。添加属性变量需要在MINIT函数中实现,在类创建完成之后,我们就可以添加属性了

        zend_class_entry tmp_myext_class_ce;
        INIT_CLASS_ENTRY(tmp_myext_class_ce,"myext_example_class",myext_class_method);
        myext_class_ce = zend_register_internal_class(&tmp_myext_class_ce TSRMLS_CC);
    //上面是创建类,下面是添加属性
    //创建普通属性和静态属性的方法是一样,只需要在第四个参数中增加ZEND_ACC_STATIC即为静态属性
    //创建类常量是另外一组的函数,和普通属性不一样 zend_declare_property_null(myext_class_ce,
    "private_prop",sizeof("private_prop")-1,ZEND_ACC_PRIVATE TSRMLS_CC);//私有权限,默认值为NULL zend_declare_property_string(myext_class_ce,"protected_prop",sizeof("protected_prop")-1,"我是默认值",ZEND_ACC_PROTECTED TSRMLS_CC);//protected权限,默认值是"我是默认值" zend_declare_property_long(myext_class_ce,"public_prop",sizeof("public_prop")-1,100,ZEND_ACC_PUBLIC TSRMLS_CC);//public,默认值是100 zend_declare_property_string(myext_class_ce,"static_prop",sizeof("static_prop")-1,"我是静态变量",ZEND_ACC_PUBLIC|ZEND_ACC_STATIC TSRMLS_CC);//静态变量,默认值是"我是静态变量" zend_declare_class_constant_string(myext_class_ce,"CONSTANT_PROP",sizeof("CONSTANT_PROP") - 1,"我是类常量" TSRMLS_CC);//类常量,默认值是"我是类常量"
    /*

    $class = new myext_example_class();
    var_dump($class);
    $class->hello();
    var_dump(myext_example_class::$static_prop);
    var_dump(myext_example_class::CONSTANT_PROP);

    object(myext_example_class)#6 (3) {
    ["private_prop":"myext_example_class":private]=>
    NULL
    ["protected_prop":protected]=>
    string(15) "我是默认值"
    ["public_prop"]=>
    int(100)
    }
    hello

    string(18) "我是静态变量"
    string(15) "我是类常量"

    */

    在php内核中,由于操作变量的类型不同,通常同样一个功能,会有一组函数,上面我们提到的创建类属性和类常量也是有一组操作。

    //以下操作都是在zend_API.h
    //定义类属性
    ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type TSRMLS_DC); ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, const char *doc_comment, int doc_comment_len TSRMLS_DC); ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, int name_length, int access_type TSRMLS_DC); ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC); ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC); ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, int name_length, double value, int access_type TSRMLS_DC); ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, int name_length, const char *value, int access_type TSRMLS_DC); ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, int name_length, const char *value, int value_len, int access_type TSRMLS_DC); //定义类常量 ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC); ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC); ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, long value TSRMLS_DC); ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value TSRMLS_DC); ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value TSRMLS_DC); 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 TSRMLS_DC); ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value TSRMLS_DC);

     接下来,我们来看一下,接口的实现,以及接口和类的继承

    定义一个接口,这个过程与定义类类似

    zend_class_entry *myext_interface_ce;
    
    static zend_function_entry myext_interface_method[] = {
        ZEND_ABSTRACT_ME(myext_interface_ce,int_func,NULL)//定义一个抽奖方法,这个方法可以不实现,也就是不需要存在一个ZEND_ME(myext_interface_ce,int_func)
        {NULL, NULL, NULL}//固定语法
    };
    
        zend_class_entry tmp_myext_interface_ce;
        INIT_CLASS_ENTRY(tmp_myext_interface_ce,"myext_example_interface",myext_interface_method);
        myext_interface_ce = zend_register_internal_interface(&tmp_myext_interface_ce TSRMLS_CC);//注册接口的函数与注册类的不一样

    /*

    class interface_class implements myext_example_interface{
    public function int_func(){
    echo "我继承了接口 ";
    }
    }

    $interface_class = new interface_class();
    $interface_class->int_func();

    我继承了接口

    */

    我们在扩展的代码里实现继承,让myext_example_class继承myext_example_interface

    ZEND_METHOD(myext_example_class,int_func);//php_myext.h
    
    //抽象函数int_func的实现
    ZEND_METHOD(myext_example_class,int_func){
    php_printf("我是class继承了接口interface");
    }
    
    
    static zend_function_entry myext_class_method[] = {
        ZEND_ME(myext_example_class,hello,NULL,ZEND_ACC_PUBLIC)
        ZEND_ME(myext_example_class,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
        ZEND_ME(myext_example_class,int_func,NULL,ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}//固定语法
    };
    
    
        zend_class_entry tmp_myext_interface_ce;
        INIT_CLASS_ENTRY(tmp_myext_interface_ce,"myext_example_interface",myext_interface_method);
        myext_interface_ce = zend_register_internal_interface(&tmp_myext_interface_ce TSRMLS_CC);
    
        zend_class_entry tmp_myext_class_ce;
        INIT_CLASS_ENTRY(tmp_myext_class_ce,"myext_example_class",myext_class_method);
        myext_class_ce = zend_register_internal_class(&tmp_myext_class_ce TSRMLS_CC);
        zend_declare_property_null(myext_class_ce,"private_prop",sizeof("private_prop")-1,ZEND_ACC_PRIVATE TSRMLS_CC);
        zend_declare_property_string(myext_class_ce,"protected_prop",sizeof("protected_prop")-1,"我是默认值",ZEND_ACC_PROTECTED TSRMLS_CC);
        zend_declare_property_long(myext_class_ce,"public_prop",sizeof("public_prop")-1,100,ZEND_ACC_PUBLIC TSRMLS_CC);
        zend_declare_property_string(myext_class_ce,"static_prop",sizeof("static_prop")-1,"我是静态变量",ZEND_ACC_PUBLIC|ZEND_ACC_STATIC TSRMLS_CC);
        zend_declare_class_constant_string(myext_class_ce,"CONSTANT_PROP",sizeof("CONSTANT_PROP") - 1,"我是类常量" TSRMLS_CC);
        zend_class_implements(myext_class_ce TSRMLS_CC,1,myext_interface_ce);//这句话表示myext_class_ce继承接口myext_interface_ce

    /*

    $class = new myext_example_class();

    $class->int_func();

    我是class继承了接口interface

    */

    我们再来实现一个类继承的例子

    ZEND_METHOD(myext_example_class,class_func);//php_myext.h
    ZEND_METHOD(myext_example_parent_class,class_func);//php_myext.h
    
    zend_class_entry *myext_parent_class_ce;//保存父类的变量
    
    static zend_function_entry myext_parent_class_method[] = {
        ZEND_ME(myext_example_parent_class,class_func,NULL,ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}//固定语法
    };
    
        zend_class_entry tmp_myext_parent_class_ce;
        INIT_CLASS_ENTRY(tmp_myext_parent_class_ce,"myext_example_parent_class",myext_parent_class_method);
        myext_parent_class_ce = zend_register_internal_class(&tmp_myext_parent_class_ce TSRMLS_CC);//注册一个myext_example_parent_class
    
        zend_class_entry tmp_myext_class_ce;
        INIT_CLASS_ENTRY(tmp_myext_class_ce,"myext_example_class",myext_class_method);
        //myext_class_ce = zend_register_internal_class(&tmp_myext_class_ce TSRMLS_CC);//正常注册类
        myext_class_ce = zend_register_internal_class_ex(&tmp_myext_class_ce,myext_parent_class_ce,"myext_example_parent_class" TSRMLS_CC);//继承注册类,第一个参数是一样的,第二个是继承父类的变量,第三个是父类的名称
        zend_declare_property_null(myext_class_ce,"private_prop",sizeof("private_prop")-1,ZEND_ACC_PRIVATE TSRMLS_CC);
        zend_declare_property_string(myext_class_ce,"protected_prop",sizeof("protected_prop")-1,"我是默认值",ZEND_ACC_PROTECTED TSRMLS_CC);
        zend_declare_property_long(myext_class_ce,"public_prop",sizeof("public_prop")-1,100,ZEND_ACC_PUBLIC TSRMLS_CC);
        zend_declare_property_string(myext_class_ce,"static_prop",sizeof("static_prop")-1,"我是静态变量",ZEND_ACC_PUBLIC|ZEND_ACC_STATIC TSRMLS_CC);
        zend_declare_class_constant_string(myext_class_ce,"CONSTANT_PROP",sizeof("CONSTANT_PROP") - 1,"我是类常量" TSRMLS_CC);
        zend_class_implements(myext_class_ce TSRMLS_CC,1,myext_interface_ce);
    
    
    ZEND_METHOD(myext_example_parent_class,class_func){
        php_printf("我是父类的class_func
    ");
    }
    
    ZEND_METHOD(myext_example_class,class_func){
        php_printf("我是子类的class_func
    ");
    }

    /*

    $parent_class = new myext_example_parent_class();
    $parent_class->class_func();
    $class = new myext_example_class();
    $class->class_func();

    我是父类的class_func
    我是__construct函数
    我是子类的class_func

    */              

    接着我们来看一下怎么样在类方法中使用类的属性变量

    ZEND_METHOD(myext_example_class,read_property){
    zval *private_prop,*protected_prop,$public_prop;
    zval *static_prop;
    zend_class_entry *ce;
    
    ce = Z_OBJCE_P(getThis());
    
    private_prop = zend_read_property(myext_class_ce,getThis(),"private_prop",sizeof("private_prop") - 1,0 TSRMLS_CC);//获取private_prop的属性值,相当于php的$this->private_prop
    php_var_dump(&private_prop,1 TSRMLS_CC);
    protected_prop = zend_read_property(myext_class_ce,getThis(),"protected_prop",sizeof("protected_prop") - 1,0 TSRMLS_CC);
    php_var_dump(&protected_prop,1 TSRMLS_CC);
    
    static_prop = zend_read_static_property(ce,"static_prop",sizeof("static_prop") - 1,0 TSRMLS_CC);//获取静态属性static_prop的属性值,相当于php的self::$static_prop
    php_var_dump(&static_prop,1 TSRMLS_CC);
    
    zend_update_property_string(myext_class_ce,getThis(),"protected_prop",sizeof("protected_prop") - 1,"更新protected_prop的值" TSRMLS_CC);//设置protected_prop的属性值,相当于php的$this->protected_prop = "更新protected_prop";
    protected_prop = zend_read_property(myext_class_ce,getThis(),"protected_prop",sizeof("protected_prop") - 1,0 TSRMLS_CC);
    php_var_dump(&protected_prop,1 TSRMLS_CC);
    
    zend_update_static_property_string(myext_class_ce,"static_prop",sizeof("static_prop") - 1,"更新static_prop的值" TSRMLS_CC);//设置静态属性static_prop的属性值,相当于php的self::$static_prop = "更新static_prop的值";
    static_prop = zend_read_static_property(ce,"static_prop",sizeof("static_prop") - 1,0 TSRMLS_CC); 

    php_var_dump(
    &static_prop,1 TSRMLS_CC); }
    //zend_update_property*的一组函数
    ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zval *value TSRMLS_DC);
    ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC);
    ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC);
    ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC);
    ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, int name_length, double value TSRMLS_DC);
    ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value TSRMLS_DC);
    ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, int value_length TSRMLS_DC);
    
    //zend_update_static_property*的一组函数
    ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, int name_length TSRMLS_DC); 
    ZEND_API
    int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC);
    ZEND_API
    int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC);
    ZEND_API
    int zend_update_static_property_double(zend_class_entry *scope, const char *name, int name_length, double value TSRMLS_DC);
    ZEND_API
    int zend_update_static_property_string(zend_class_entry *scope, const char *name, int name_length, const char *value TSRMLS_DC);
    ZEND_API
    int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, int name_length, const char *value, int value_length TSRMLS_DC);
    ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, int name_length, zval *value TSRMLS_DC);
  • 相关阅读:
    Scrum为什么不喜欢“来自客户的频繁变更”?
    [转]SQL Server计算列
    宽容,是创新的土壤
    【转载】《2010年年度总结》
    远程维护需要“千里眼”
    TOP语句放到表值函数外,效率异常低下
    “设计应对变化”实例讲解一个数据同步系统
    “批量少次”还是“少量多次”邮件通信系统效率浅谈
    NYOJ117 求逆序数
    NYOJ92 图像有用区域
  • 原文地址:https://www.cnblogs.com/wuhen781/p/6237232.html
Copyright © 2011-2022 走看看