PHP函数原理(Introspecting PHP Function)

·        作者Laruence(   )

·        本文地址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个结构:

1.       typedefstruct _zend_internal_function {

2.           /* Common elements */

3.           zend_uchar type;

4.           char * function_name;

5.           zend_class_entry *scope;

6.           zend_uint fn_flags;

7.           union _zend_function *prototype;

8.           zend_uint num_args;

9.           zend_uint required_num_args;

10.        zend_arg_info *arg_info;

11.        zend_bool pass_rest_by_reference;

12.        unsignedchar return_reference;

13.        /* END of common elements */

14.     

15.        void (*handler)(INTERNAL_FUNCTION_PARAMETERS);

16.        struct _zend_module_entry *module;

17.    } zend_internal_function;

18.     

19.    struct _zend_op_array {

20.        /* Common elements */

21.        zend_uchar type;

22.        char *function_name;

23.        zend_class_entry *scope;

24.        zend_uint fn_flags;

25.        union _zend_function *prototype;

26.        zend_uint num_args;

27.        zend_uint required_num_args;

28.        zend_arg_info *arg_info;

29.        zend_bool pass_rest_by_reference;

30.        unsignedchar return_reference;

31.        /* END of common elements */

32.     

33.        zend_uint *refcount;

34.     

35.        zend_op *opcodes;

36.        zend_uint last, size;

37.     

38.        zend_compiled_variable *vars;

39.        int last_var, size_var;

40.     

41.        zend_uint T;

42.     

43.        zend_brk_cont_element *brk_cont_array;

44.        zend_uint last_brk_cont;

45.        zend_uint current_brk_cont;

46.     

47.        zend_try_catch_element *try_catch_array;

48.        int last_try_catch;

49.     

50.        /* static variables support */

51.        HashTable *static_variables;

52.     

53.        zend_op *start_op;

54.        int backpatch_count;

55.     

56.        zend_bool done_pass_two;

57.        zend_bool uses_this;

58.     

59.        char *filename;

60.     

61.         zend_uint line_start;

62.        zend_uint line_end;

63.        char *doc_comment;

64.        zend_uint doc_comment_len;

65.     

66.        void *reserved[ZEND_MAX_RESERVED_RESOURCES];

67.    };

68.     

69.    typedefunion _zend_function {

70.        zend_uchar type;    /* MUST be the first element of this struct!*/

71.     

72.        struct {

73.            zend_uchar type;  /* never used */

74.            char *function_name;

75.            zend_class_entry *scope;

76.            zend_uint fn_flags;

77.            union _zend_function *prototype;

78.            zend_uint num_args;

79.            zend_uint required_num_args;

80.            zend_arg_info *arg_info;

81.            zend_bool pass_rest_by_reference;

82.            unsignedchar return_reference;

83.        } common;

84.     

85.        zend_op_array op_array;

86.        zend_internal_function internal_function;

87.    } zend_function;

88.       

第一个结构,定义了zend_internal_function, PHP启动的时候,它会遍历每个载入的扩展模块,然后将模块中function_entry中指明的每一个函数,创建一个zend_internal_function结构,并将type置为ZEND_INTERNAL_FUNCTION(见下表), 将这个结构填入全局的函数表(一个HashTable);

1.       #define ZEND_INTERNAL_FUNCTION              1

2.       #define ZEND_USER_FUNCTION                  2

3.       #define ZEND_OVERLOADED_FUNCTION            3

4.       #define ZEND_EVAL_CODE                      4

5.       #define ZEND_OVERLOADED_FUNCTION_TEMPORARY  5

6.            

第二个结构,op_array, 这个结构很重要,因为:

1.             extern ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);

2.         

也就是说,我们编写的PHP脚本,都会被ZE翻译成op_array, 最后交由zend_execute执行。

另外,在ZE中,用户定义的函数(userland function), 也会被翻译成一个op_array, 并填入全局函数表中。这个时候scope,function_name都不为空。而对于在全局作用域的直接代码来说,最后的op_arrayscope为全局,function_name为空。

第三个结构,很有趣,要理解这个结构,首先你要理解他的设计目标: zend_internal_function,zend_function,zend_op_array可以安全的互相转换(The are not identical structs, but all the elements thatare in “common” they hold in common, thus the can safely be casted to eachother);

具体来说,当在op code中通过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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值