@@ -88,16 +88,48 @@ function my_function(){
88
88
另外参数还有其它的信息,比如默认值、引用传递,这些信息通过` zend_arg_info ` 结构记录:
89
89
``` c
90
90
typedef struct _zend_arg_info {
91
- zend_string *name; //函数名
91
+ zend_string *name; //参数名
92
92
zend_string *class_name;
93
93
zend_uchar type_hint; //显式声明的参数类型,比如(array $param_1)
94
94
zend_uchar pass_by_reference; //是否引用传参,参数前加&的这个值就是1
95
- zend_bool allow_null; //是否允许为空
95
+ zend_bool allow_null; //是否允许为NULL,注意:这个值并不是用来表示参数是否为必传的
96
96
zend_bool is_variadic; //是否为可变参数,即...用法,与golang的用法相同,5.6以上新增的一个用法
97
97
} zend_arg_info;
98
98
```
99
- 每个参数都有一个上面的结构,所有参数的结构保存在` zend_op_array.arg_info ` 数组中。
99
+ 每个参数都有一个上面的结构,所有参数的结构保存在` zend_op_array.arg_info ` 数组中,这里有一个地方需要注意:` zend_op_array->arg_info ` 数组保存的并不全是输入参数,如果函数声明了返回值类型则也会为它创建一个` zend_arg_info ` ,这个结构在arg_info数组的第一个位置,这种情况下` zend_op_array->arg_info ` 指向的实际是数组的第二个位置,返回值的结构通过` zend_op_array->arg_info[-1] ` 读取,编译时的处理具体如下。
100
+ ``` c
101
+ // 函数参数的编译
102
+ void zend_compile_params (zend_ast * ast, zend_ast * return_type_ast)
103
+ {
104
+ zend_ast_list * list = zend_ast_get_list(ast);
105
+ uint32_t i;
106
+ zend_op_array * op_array = CG(active_op_array);
107
+ zend_arg_info * arg_infos;
108
+
109
+ if (return_type_ast) {
110
+ //声明了返回值类型:function my_func():array{...}
111
+ //多分配一个zend_arg_info
112
+ arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0);
113
+ ...
114
+ arg_infos->allow_null = 0;
115
+ ...
116
+ //arg_infos指向了下一个位置
117
+ arg_infos++;
118
+ op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
119
+ } else {
120
+ //没有声明返回值类型
121
+ if (list->children == 0) {
122
+ return;
123
+ }
124
+ arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children, 0);
125
+ }
126
+ ...
100
127
128
+ op_array->num_args = list->children;
129
+ //声明了返回值的情况下arg_infos已经指向了数组的第二个元素
130
+ op_array->arg_info = arg_infos;
131
+ }
132
+ ```
101
133
#### 3.2.1.3 函数的编译
102
134
我们在上一篇文章介绍过PHP代码的编译过程,主要是PHP->AST->Opcodes的转化,上面也说了函数其实就是将一组PHP代码编译为单独的opcodes,函数的调用就是不同opcodes间的切换,所以函数的编译过程与普通PHP代码基本一致,只是会有一些特殊操作,我们以3.2.1.2开始那个例子简单看下编译过程。
103
135
0 commit comments