加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

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

发布时间:2020-12-13 21:23:04 所属栏目: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

原文: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,int return_v??? alue_used TSRMLS_DC )

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

1
2
3
ZEND_BEGIN_ARG_INFO_EX(arg_person_info,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,NULL,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,pass_by_ref,0 },

这三个宏 执行代码 等于

1
2
3
static const zend_arg_info name[] = {??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? { NULL,
{ #name,sizeof(#name)-1,
};

3.创建zend_function_entry结构数组

1
2
3
4
5
6
7
const zend_function_entry person_functions[]={
????????PHP_ME(Person,__construct,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
????????PHP_ME(Person,__destruct,ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
????????PHP_ME(Person,getproperty,arg_person_info,ZEND_ACC_PUBLIC)
????????PHP_ME(Person,setproperty,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 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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读