zoukankan      html  css  js  c++  java
  • [转]自己写PHP扩展之创建一个类

    原文:http://www.imsiren.com/archives/572

    比如我们要创建一个类..PHP代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class Person {
        public $name;
        public $age;
        public function __construct() {
            echo "construct is running!
    ";
        }
        public function __destruct() {
            echo "
    destruct is running!";
        }
        public function getproperty($key) {
            echo $this->$key;
        }
        public function setproperty($key,$val) {
            $this->$key = $val;
        }
    }

    用PHP来做,很简单..
    那么用PHP扩展来写该怎么做?
    OK.
    1.在php_siren.h里面声明类

    1
    2
    3
    4
    PHP_METHOD(Person,__construct);
    PHP_METHOD(Person,__destruct);
    PHP_METHOD(Person,setproperty);
    PHP_METHOD(Person,getproperty);

    PHP_METHOD宏.
    PHP_METHOD 等于ZEND_METHOD
    这个宏接受两个参数,第一个是类名,第二个是类的方法

    1
    2
    3
    4
    #define ZEND_METHOD(classname, name)    ZEND_NAMED_FUNCTION(ZEND_MN(classname##_##name))
    #define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_v    alue_used TSRMLS_DC
    //最后等于
    void name(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_v    alue_used TSRMLS_DC )

    这个宏是用来声明我们的方法…
    2.设置接收的参数
    我们的方法如果需要接受参数.那么就要执行

    1
    2
    3
    ZEND_BEGIN_ARG_INFO_EX(arg_person_info,0,0,2)
            ZEND_ARG_INFO(0,name)
    ZEND_END_ARG_INFO()

    详细讲这几个宏之前先看看zend_arg_info

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef struct _zend_arg_info {
            const char *name; //参数名称
            zend_uint name_len;//长度
            const char *class_name;  //所属类名
            zend_uint class_name_len;  //类名长度
            zend_bool array_type_hint;
            zend_bool allow_null; //允许为空
            zend_bool pass_by_reference;  //引用传值
            zend_bool return_reference;   //引用返回
            int required_num_args;   //参数个数
    } zend_arg_info;

    ZEND_BEGIN_ARG_INFO_EX定义在Zend/zend_API.h

    1
    2
    3
    #define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args)      
            static const zend_arg_info name[] = {                                                                                                                                          
                    { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },

    很明显 声明一个zend_arg_info的数组name,然后初始化结构体的值
    ZEND_ARG_INFO(0,name)的定义如下

    1
    #define ZEND_ARG_INFO(pass_by_ref, name)  { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 },

    这三个宏 执行代码 等于

    1
    2
    3
    static const zend_arg_info name[] = {                                                                                                                                                    { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },
    { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 },
    };

    3.创建zend_function_entry结构数组

    1
    2
    3
    4
    5
    6
    7
    const zend_function_entry person_functions[]={
            PHP_ME(Person,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
            PHP_ME(Person,__destruct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
            PHP_ME(Person,getproperty,arg_person_info,ZEND_ACC_PUBLIC)
            PHP_ME(Person,setproperty,arg_person_info,ZEND_ACC_PUBLIC)
            PHP_FE_END
    };

    zend_function_entry定义如下

    1
    2
    3
    4
    5
    6
    7
    typedef struct _zend_function_entry {
            const char *fname; //函数名称
            void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
            const struct _zend_arg_info *arg_info;//参数
            zend_uint num_args;//参数个数
            zend_uint flags;//标示PUBLIC ?PRIVATE ?PROTECTED
    } zend_function_entry;

    PHP_ME宏接收四个参数
    1 类名,
    2 方法名,
    3 zend_arg_info 的参数列表,

    ZEND_ACC_PUBLIC ZEND_ACC_PRIVATE ZEND_ACC_PROTECTED是我们类里面的三个访问权限
    ZEND_ACC_CTOR标示构造函数
    ZEND_ACC_DTOR标示析构函数
    4.修改PHP_MINIT_FUNCTION
    前面我们说过 PHP_MINIT_FUNCTION是在模块启动的时候执行的函数
    首先创建一个全局指针 zend_class_entry *person_ce;
    在PHP_MINIT_FUNCTION加入如下代码

    1
    2
    3
    4
    zend_class_entry person;
    INIT_CLASS_ENTRY(person,"Person",person_functions);
    person_ce=zend_register_internal_class_ex(&person,NULL,NULL TSRMLS_CC);
    zend_declare_property_null(person_ce,ZEND_STRL("name"),ZEND_ACC_PUBLIC TSRMLS_CC);

    1行创建一个zend_class_entry对象person.
    zend_class_entry这个结构体前面也讲过 PHP内核研究之类的实现
    2行初始化zend_class_entry 它执行了如下代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    {                                                                                                                      
            int _len = class_name_len;                                                             
            class_container.name = zend_strndup(class_name, _len); 
            class_container.name_length = _len;                                            
            class_container.builtin_functions = functions;                 
            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.interfaces = NULL;                                             
            class_container.get_iterator = NULL;                                   
            class_container.iterator_funcs.funcs = NULL;                   
            class_container.module = NULL;                                                 
    }

    可以对应文章>> PHP内核研究之类的实现来分析
    zend_declare_property_null(person_ce,ZEND_STRL(“name”),ZEND_ACC_PUBLIC TSRMLS_CC);
    创建一个值为NULL的属性
    第一个参数是类名,第二个参数是 属性名称,第三个参数是属性名的长度,因为ZEND_STRL宏定义了长度,所以这里不用再传递长度.
    第四个参数是属性的访问权限.
    还有其他几个函数用来创建不同类型的属性

    1
    2
    3
    4
    5
    6
    7
    zend_declare_property_bool
    zend_declare_property_double
    zend_declare_property_ex
    zend_declare_property_long
    zend_declare_property_null
    zend_declare_property_string
    zend_declare_property_stringl

    5.创建 php_siren.h头文件中的方法体

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    PHP_METHOD(Person,__construct){
            php_printf("construct is running<br>");
    }
    PHP_METHOD(Person,__destruct){
            php_printf("destruct is running<br>");
    }
    PHP_METHOD(Person,setproperty){
     
    }
    PHP_METHOD(Person,getproperty){
     
    }

    6.最后make&& make install
    编译我们的扩展,
    重新启动apache.
    $p=new Person();
    ?>
    我们就能在浏览器里看到输出的内容

    construct is running
    destruct is running

    这样 ..我们用扩展创建的一个基本类就完成了.

  • 相关阅读:
    Simple DirectMedia Layer常用API总结
    [游戏复刻] Super Mario Brothers(1985. Famicom)
    [游戏复刻] 2048(2014. Android)
    图的结构以及寻路算法的c实现
    散列查找的C实现
    【游戏编程从0开始】一、基本结构
    C++中const关键字用法总结
    C标准库常用函数概要
    字符串表达式计算器的设计
    初探数据结构
  • 原文地址:https://www.cnblogs.com/orlion/p/5466164.html
Copyright © 2011-2022 走看看