Skip to content

Commit fc4943d

Browse files
committed
add class register
1 parent f167bb6 commit fc4943d

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

7/class.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
## 7.9 面向对象
2+
### 7.9.1 定义内部类
3+
在扩展中定义一个内部类的方式与函数类似,函数最终注册到EG(function_table),而类则最终注册到EG(class_table)符号表中,注册的过程首先是为类创建一个zend_class_entry结构,然后把这个结构插入EG(class_table),当然这个过程不需要我们手动操作,PHP提供了现成的方法和宏帮我们对zend_class_entry进行初始化以及注册。通常情况下会把内部类的注册放到module startup阶段,也就是定义在扩展的`PHP_MINIT_FUNCTION()`中,一个简单的类的注册只需要以下几行:
4+
```c
5+
PHP_MINIT_FUNCTION(mytest)
6+
{
7+
//分配一个zend_class_entry,这个结构只在注册时使用,所以分配在栈上即可
8+
zend_class_entry ce;
9+
//对zend_class_entry进行初始化
10+
INIT_CLASS_ENTRY(ce, "MyClass", NULL);
11+
//注册
12+
zend_register_internal_class(&ce);
13+
}
14+
```
15+
这样就成功定义了一个内部类,类名为"MyClass",只是这个类还没有任何的成员属性、成员方法,定义完成后重新编译、安装扩展,然后在PHP脚本中实例化这个类:
16+
```php
17+
$obj = new MyClass();
18+
19+
var_dump($obj);
20+
```
21+
结果将输出:
22+
```
23+
object(MyClass)#1 (0) {
24+
}
25+
```
26+
注册时传入的zend_class_entry并不是最终插入class_table符号表的结构,zend_register_internal_class()中会重新分配,所以注册时的这个结构分配在栈上即可,此结构的成员不需要手动定义,PHP提供了宏供扩展使用,扩展只需要提供类的主要信息即可,常用的两个宏:
27+
```c
28+
/**
29+
* 初始化zend_class_entry
30+
* class_container:zend_class_entry地址
31+
* class_name:类名
32+
* functions:成员方法数组
33+
*/
34+
#define INIT_CLASS_ENTRY(class_container, class_name, functions) \
35+
INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, NULL, NULL, NULL)
36+
37+
/**
38+
* 初始化zend_class_entry,带namespace
39+
* class_container:zend_class_entry地址
40+
* ns:命名空间
41+
* class_name:类名
42+
* functions:成员方法数组
43+
*/
44+
#define INIT_NS_CLASS_ENTRY(class_container, ns, class_name, functions) \
45+
INIT_CLASS_ENTRY(class_container, ZEND_NS_NAME(ns, class_name), functions)
46+
```
47+
48+
### 7.9.2 定义成员属性
49+
50+
### 7.9.3 定义成员方法
51+
52+
### 7.9.4 定义常量
53+
54+
### 7.9.5 类的实例化

0 commit comments

Comments
 (0)