PHP函数的内部实现
时间:2008-08-16
来源:互联网
PHP的函数(Introspecting PHP Function)
・作者:laruence(http://www.laruence.com/)
・ 本文地址: http://www.laruence.com/2008/08/12/164.html
・ 转载请注明出处
在PHP中,函数分为俩种,
一种是zend_internal_function, 这种函数是由扩展或者Zend/PHP内核提供的,用’C/C++’编写的,可以直接执行的函数。另外一种是zend_user_function, 这种函数呢,就是我们经常在见的,用户在PHP脚本中定义的函数,这种函数最终会被ZE翻译成opcode array来执行 查看zend_compile.h,我们可以找到如下的3个结构:
typedef
struct
_zend_internal_function
{
/* Common elements */
zend_uchar
type;
char * function_name;
zend_class_entry *scope;
zend_uint
fn_flags;
union
_zend_function *prototype;
zend_uint
num_args;
zend_uint
required_num_args;
zend_arg_info *arg_info;
zend_bool
pass_rest_by_reference;
unsigned
char
return_reference;
/* END of common elements */
void
(*handler)(INTERNAL_FUNCTION_PARAMETERS);
struct
_zend_module_entry *module;
}
zend_internal_function;
struct
_zend_op_array
{
/* Common elements */
zend_uchar
type;
char *function_name;
zend_class_entry *scope;
zend_uint
fn_flags;
union
_zend_function *prototype;
zend_uint
num_args;
zend_uint
required_num_args;
zend_arg_info *arg_info;
zend_bool
pass_rest_by_reference;
unsigned
char
return_reference;
/* END of common elements */
zend_uint *refcount;
zend_op *opcodes;
zend_uint
last, size;
zend_compiled_variable *vars;
int
last_var, size_var;
zend_uint
T;
zend_brk_cont_element *brk_cont_array;
zend_uint
last_brk_cont;
zend_uint
current_brk_cont;
zend_try_catch_element *try_catch_array;
int
last_try_catch;
/* static variables support */
HashTable *static_variables;
zend_op *start_op;
int
backpatch_count;
zend_bool
done_pass_two;
zend_bool
uses_this;
char *filename;
zend_uint
line_start;
zend_uint
line_end;
char *doc_comment;
zend_uint
doc_comment_len;
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};
typedef
union
_zend_function
{
zend_uchar
type; /* MUST be the first element of this struct! */
struct
{
zend_uchar
type; /* never used */
char *function_name;
zend_class_entry *scope;
zend_uint
fn_flags;
union
_zend_function *prototype;
zend_uint
num_args;
zend_uint
required_num_args;
zend_arg_info *arg_info;
zend_bool
pass_rest_by_reference;
unsigned
char
return_reference;
}
common;
zend_op_array
op_array;
zend_internal_function
internal_function;
}
zend_function;
第一个结构,定义了zend_internal_function, 当PHP启动的时候,它会遍历每个载入的扩展模块,然后将模块中function_entry中指明的每一个函数,创建一个zend_internal_function结构, 并将type置为ZEND_INTERNAL_FUNCTION(见下表),将这个结构填入全局的函数表(一个HashTable);
#define
ZEND_INTERNAL_FUNCTION
1
#define
ZEND_USER_FUNCTION
2
#define
ZEND_OVERLOADED_FUNCTION
3
#define
ZEND_EVAL_CODE
4
#define
ZEND_OVERLOADED_FUNCTION_TEMPORARY
5
第二个结构,op_array, 这个结构很重要, 因为:
extern
ZEND_API
zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int
type
TSRMLS_DC);
也就是说,我们编写的PHP脚本,都会被ZE翻译成op_array, 最后交由zend_execute执行。
另外,在ZE中,用户定义的函数(userland function), 也会被翻译成一个op_array,并填入全局函数表中。这个时候scope,function_name都不为空。而对于在全局作用域的直接代码来说,最后的op_array的scope为全局,function_name为空。
第三个结构, 很有趣, 要理解这个结构,首先你要理解他的设计目标: zend_internal_function,zend_function,zend_op_array可以安全的互相转换(The are not identical structs, butall the elements that are in “common” they hold in common, thus the cansafely be casted to each other);
具体来说,当在opcode中通过ZEND_DO_FCALL调用一个函数的时候,ZE会在函数表中,根据名字(其实是lowercase的函数名字,这也就是为什么PHP的函数名是大小写不敏感的)查找函数,如果找到,返回一个zend_function结构的指针(仔细看这个上面的zend_function结构),然后判断type,如果是ZEND_INTERNAL_FUNCTION,那么ZE就调用zend_execute_internal,通过zend_internal_function.handler来执行这个函数,如果不是,就调用zend_execute来执行这个函数包含的zend_op_array.
[ 本帖最后由 laruence 于 2008-8-16 12:43 编辑 ]
・作者:laruence(http://www.laruence.com/)
・ 本文地址: http://www.laruence.com/2008/08/12/164.html
・ 转载请注明出处
在PHP中,函数分为俩种,
一种是zend_internal_function, 这种函数是由扩展或者Zend/PHP内核提供的,用’C/C++’编写的,可以直接执行的函数。另外一种是zend_user_function, 这种函数呢,就是我们经常在见的,用户在PHP脚本中定义的函数,这种函数最终会被ZE翻译成opcode array来执行 查看zend_compile.h,我们可以找到如下的3个结构:
typedef
struct
_zend_internal_function
{
/* Common elements */
zend_uchar
type;
char * function_name;
zend_class_entry *scope;
zend_uint
fn_flags;
union
_zend_function *prototype;
zend_uint
num_args;
zend_uint
required_num_args;
zend_arg_info *arg_info;
zend_bool
pass_rest_by_reference;
unsigned
char
return_reference;
/* END of common elements */
void
(*handler)(INTERNAL_FUNCTION_PARAMETERS);
struct
_zend_module_entry *module;
}
zend_internal_function;
struct
_zend_op_array
{
/* Common elements */
zend_uchar
type;
char *function_name;
zend_class_entry *scope;
zend_uint
fn_flags;
union
_zend_function *prototype;
zend_uint
num_args;
zend_uint
required_num_args;
zend_arg_info *arg_info;
zend_bool
pass_rest_by_reference;
unsigned
char
return_reference;
/* END of common elements */
zend_uint *refcount;
zend_op *opcodes;
zend_uint
last, size;
zend_compiled_variable *vars;
int
last_var, size_var;
zend_uint
T;
zend_brk_cont_element *brk_cont_array;
zend_uint
last_brk_cont;
zend_uint
current_brk_cont;
zend_try_catch_element *try_catch_array;
int
last_try_catch;
/* static variables support */
HashTable *static_variables;
zend_op *start_op;
int
backpatch_count;
zend_bool
done_pass_two;
zend_bool
uses_this;
char *filename;
zend_uint
line_start;
zend_uint
line_end;
char *doc_comment;
zend_uint
doc_comment_len;
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};
typedef
union
_zend_function
{
zend_uchar
type; /* MUST be the first element of this struct! */
struct
{
zend_uchar
type; /* never used */
char *function_name;
zend_class_entry *scope;
zend_uint
fn_flags;
union
_zend_function *prototype;
zend_uint
num_args;
zend_uint
required_num_args;
zend_arg_info *arg_info;
zend_bool
pass_rest_by_reference;
unsigned
char
return_reference;
}
common;
zend_op_array
op_array;
zend_internal_function
internal_function;
}
zend_function;
第一个结构,定义了zend_internal_function, 当PHP启动的时候,它会遍历每个载入的扩展模块,然后将模块中function_entry中指明的每一个函数,创建一个zend_internal_function结构, 并将type置为ZEND_INTERNAL_FUNCTION(见下表),将这个结构填入全局的函数表(一个HashTable);
#define
ZEND_INTERNAL_FUNCTION
1
#define
ZEND_USER_FUNCTION
2
#define
ZEND_OVERLOADED_FUNCTION
3
#define
ZEND_EVAL_CODE
4
#define
ZEND_OVERLOADED_FUNCTION_TEMPORARY
5
第二个结构,op_array, 这个结构很重要, 因为:
extern
ZEND_API
zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int
type
TSRMLS_DC);
也就是说,我们编写的PHP脚本,都会被ZE翻译成op_array, 最后交由zend_execute执行。
另外,在ZE中,用户定义的函数(userland function), 也会被翻译成一个op_array,并填入全局函数表中。这个时候scope,function_name都不为空。而对于在全局作用域的直接代码来说,最后的op_array的scope为全局,function_name为空。
第三个结构, 很有趣, 要理解这个结构,首先你要理解他的设计目标: zend_internal_function,zend_function,zend_op_array可以安全的互相转换(The are not identical structs, butall the elements that are in “common” they hold in common, thus the cansafely be casted to each other);
具体来说,当在opcode中通过ZEND_DO_FCALL调用一个函数的时候,ZE会在函数表中,根据名字(其实是lowercase的函数名字,这也就是为什么PHP的函数名是大小写不敏感的)查找函数,如果找到,返回一个zend_function结构的指针(仔细看这个上面的zend_function结构),然后判断type,如果是ZEND_INTERNAL_FUNCTION,那么ZE就调用zend_execute_internal,通过zend_internal_function.handler来执行这个函数,如果不是,就调用zend_execute来执行这个函数包含的zend_op_array.
[ 本帖最后由 laruence 于 2008-8-16 12:43 编辑 ]
作者: laruence 发布时间: 2008-08-16
写的很好,收藏了。
作者: happyboy 发布时间: 2008-08-16
呵呵,造福大家。
作者: laruence 发布时间: 2008-08-16
不错,支持下啦

作者: 追风1 发布时间: 2008-08-18
恩,我觉得这些知识,了解一下对PHP还是很有好处的
哪怕你并不想了解PHP核心,但是稍微知道点,还是会受益匪浅的。
哪怕你并不想了解PHP核心,但是稍微知道点,还是会受益匪浅的。
作者: laruence 发布时间: 2008-08-19
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28