您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

[转]自己写PHP扩展之创建一个类 - orlion

2024/4/11 16:48:02发布131次查看
原文: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
);
}
php_method(person,__destruct){
        php_printf(destruct is running
);
}
php_method(person,setproperty){
}
php_method(person,getproperty){
}
6.最后make&& make install
编译我们的扩展,
重新启动apache.
$p=new person();
?>
我们就能在浏览器里看到输出的内容
construct is running
destruct is running
这样 ..我们用扩展创建的一个基本类就完成了.
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product