1.函數的存儲結構數組
typedef union _zend_function zend_function; union _zend_function { zend_uchar type; struct { zend_uchar type; zend_uchar arg_flags[3]; uint32_t fn_flags; zend_string *function_name; zend_class_entry *scope; //成員方法所屬類,面向對象實現中用到 union _zend_function *prototype; uint32_t num_args; //參數數量 uint32_t required_num_args; //必傳參數數量 zend_arg_info *arg_info; //參數信息 } common; zend_op_array op_array; //自定義函數(函數實際編譯爲普通的zend_op_array) zend_internal_function internal_function; //內部函數(經過擴展或者內核提供的C函數) };
zend_function.common.xx快速訪問到zend_function.zend_op_array.xx及zend_function.zend_internal_function.xx zend_function.type取到zend_function.op_array.type及zend_function.internal_function.type
PHP在編譯階段將用戶自定義的函數編譯爲獨立的opcodes,保存在EG(function_table)中,調用時從新分配新的zend_execute_data(至關於運行棧),而後執行函數的opcodes,調用完再還原到舊的zend_execute_data,繼續執行,EG(function_table)是一個哈希表,記錄的就是PHP中全部的函數
2.函數參數函數
函數參數在內核實現上與函數內的局部變量實際是同樣的,提供一個單獨的編號,參數名稱也在zend_op_array.vars中,編號首先是從參數開始的,因此按照參數順序其編號依次爲0、一、2...(轉化爲相對內存偏移量就是9六、1十二、128...),而後函數調用時首先會在調用位置將參數的value複製到各參數各自的位置
//參數的額外信息 typedef struct _zend_arg_info { zend_string *name; //參數名 zend_string *class_name; zend_uchar type_hint; //顯式聲明的參數類型,好比(array $param_1) zend_uchar pass_by_reference; //是否引用傳參,參數前加&的這個值就是1 zend_bool allow_null; //是否容許爲NULL zend_bool is_variadic; //是否爲可變參數,即...用法,function my_func($a, ...$b){...} } zend_arg_info;
每一個參數都有一個上面的結構,全部參數的結構保存在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]讀取
3.內部函數ui
內部函數指的是由內核、擴展提供的C語言編寫的function,這類函數不須要經歷opcode的編譯過程,因此效率上要高於PHP用戶自定義的函數,調用時與普通的C程序沒有差別。Zend引擎中定義了不少內部函數供用戶在PHP中使用,好比:define、defined、strlen、method_exists、class_exists、function_exists......等等,除了Zend引擎中定義的內部函數,PHP擴展中也提供了大量內部函數,咱們也能夠靈活的經過擴展自行定製。
//zend_internal_function頭部是一個與zend_op_array徹底相同的common結構 typedef struct _zend_internal_function { /* Common elements */ zend_uchar type; zend_uchar arg_flags[3]; /* bitset of arg_info.pass_by_reference */ uint32_t fn_flags; zend_string* function_name; zend_class_entry *scope; zend_function *prototype; uint32_t num_args; uint32_t required_num_args; zend_internal_arg_info *arg_info; /* END of common elements */ void (*handler)(INTERNAL_FUNCTION_PARAMETERS); //函數指針,展開:void (*handler)(zend_execute_data *execute_data, zval *return_value) struct _zend_module_entry *module; void *reserved[ZEND_MAX_RESERVED_RESOURCES]; } zend_internal_function;