In-depth understanding of the internal structure of PHP kernel (5) functions php functions include user-defined functions and internal functions (print_rcount ...), anonymous function, variable function ($ funcprint_r; $ func (array (a, B ));) in the PHP kernel source code, functions are divided into the following types: # defineZEND_INTERNAL_FUNCTION1 # defi deep understanding of the internal structure of PHP kernel (5) functions
Php functions include user-defined functions and internal functions (print_r count ...), anonymous function, variable function ($ func = 'print _ R'; $ func (array ('A', 'B '));)
Functions are classified into the following types in the PHP kernel source code:
#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
1. user functions (ZEND_USER_FUNCTION)
Functions do not necessarily return values explicitly. in PHP implementation, even if there is no explicit return, the PHP kernel will return NULL.
During ZEND execution, the runtime information is stored in _ zend_execute_data:
Struct _ zend_execute_data {//... omitting some code zend_function_state function_state; zend_function * fbc;/* Function Being Called * //... omitting some code };
During program initialization, function_state is also initialized. function_state consists of two parts:
typedef struct _zend_function_state { zend_function *function; void **arguments;} zend_function_state;
* Arguments is a pointer to a function parameter, and the function body is stored in * function. * function is a zend_function struct that stores all information about a user-defined function, the specific structure is as follows:
Typedef union _ zend_function {zend_uchar type;/* MUST be the first element of this struct! */Struct {zend_uchar type;/* never used */char * function_name; // Function name zend_class_entry * scope; // Function class scope zend_uint fn_flags; // Function type, for example, the user-defined value is # define ZEND_USER_FUNCTION 2 union _ zend_function * prototype; // Function prototype zend_uint num_args; // Number of zend_uint arguments; // The number of required parameters zend_arg_info * arg_info; // parameter information pointer zend_bool pass_rest_by_reference; unsigned char return_reference; // return value} common; ze Nd_op_array op_array; // operations in the function? Zend_internal_function internal_function;} zend_function;
Op_array in the structure of zend_function stores all operations in this function. when the function is called, ZEND will execute the opline in this op_array in sequence and return the final result. Function definition and execution are separated. a function can be used as an independent running unit.
II. internal functions (ZEND_INTERNAL_FUNCTION)
ZEND_INTERNAL_FUNCTION is provided by the extension or Zend/PHP Kernel. it can be directly executed in c/c ++. The structure of the internal function is as follows:
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;
During module initialization, ZE traverses each loaded extension module, and then creates a zend_internal_function structure for each function specified in function_entry in the module (module-> functions, set its type to ZEND_INTERNAL_FUNCTION, and fill in this structure in the global function table (HashTable structure). For the function setting and registration process, see the zend_register_function function in the Zend/zene_API.c file, in addition to processing function pages, this function also processes class methods, including magic methods.
The structure of internal functions is similar to that of user-defined functions:
- Call method: handler Field. if it is ZEND_INTERNAL_FUNCTION, ZEND will call zend_execute_internal to execute this function through zend_internal_function.handler. User-defined functions need to generate intermediate code, and then map the intermediate code to the opposite to call the method.
- The built-in function has a module field in the structure to indicate which module it belongs. Different extension modules
- Type field. in user-defined functions, the type field is almost useless, while the type field in the built-in function is used as a distinction between several internal functions.
III. variable functions
If a variable name is enclosed by parentheses, php searches for a function with the same name as the value of the variable and tries to execute the function.
Variable functions $ func
$func = 'print_r';$func('i am print_r function.');
Intermediate code after Compilation
function name: (null)number of ops: 9compiled vars: !0 = $funcline # * op fetch ext return operands-------------------------------------------------------------------------------- 2 0 > EXT_STMT 1 ASSIGN !0, 'print_r' 3 2 EXT_STMT 3 INIT_FCALL_BY_NAME !0 4 EXT_FCALL_BEGIN 5 SEND_VAL 'i+am+print_r+function.' 6 DO_FCALL_BY_NAME 1 7 EXT_FCALL_END 8 > RETURN 1
Internal functions
print_r('i am print_r function.');
Intermediate code after Compilation
function name: (null)number of ops: 6compiled vars: noneline # * op fetch ext return operands--------------------------------------------------------------------------------- 2 0 > EXT_STMT 1 EXT_FCALL_BEGIN 2 SEND_VAL 'i+am+print_r+function.' 3 DO_FCALL 1 'print_r' 4 EXT_FCALL_END 5 > RETURN 1
The comparison shows that there are some differences between the two in calling the intermediate code. the variable function is DO_FCALL_BY_NAME, and the internal function is DO_FCALL. This is determined by syntax parsing. see some code in the zend_do_end_function_call function of the Zend/zend_complie.c file:
if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) { opline->opcode = ZEND_DO_FCALL; opline->op1 = *function_name; ZVAL_LONG(&opline->op2.u.constant, zend_hash_func(Z_STRVAL(function_name->u.constant), Z_STRLEN(function_name->u.constant) + 1)); } else { opline->opcode = ZEND_DO_FCALL_BY_NAME; SET_UNUSED(opline->op1); }
If it is not a method and is not a dynamic call, and the function name is a string variable, the intermediate code generated is ZEND_DO_FCALL. In other cases, ZEND_DO_FCALL_BY_NAME is used. In addition, the variable function is used as the callback function, and its processing process is in the zend_do_pass_param function of the Zend/zend_complie.c file. it will eventually be reflected in the ZEND_SEND_VAL_SPEC_CONST_HADNLER function during Intermediate.
IV. anonymous functions
An anonymous function is a type of function or subroutine that can be called without a designated identifier. an anonymous function can be conveniently passed as a parameter to other functions.