Home  >  Article  >  Backend Development  >  In-depth understanding of parameter passing of PHP custom functions

In-depth understanding of parameter passing of PHP custom functions

伊谢尔伦
伊谢尔伦Original
2017-06-26 13:29:151483browse

Parameters of function

The definition of a function is just a process of registering the function name to the function list.

1. User Parameters of custom function

We know that the parameter check of the function is implemented through the zend_do_receive_arg function. In this function, the key code for the parameters is As follows:

CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info,
        sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
cur_arg_info->name = estrndup(varname->u.constant.value.str.val,
        varname->u.constant.value.str.len);
cur_arg_info->name_len = varname->u.constant.value.str.len;
cur_arg_info->array_type_hint = 0;
cur_arg_info->allow_null = 1;
cur_arg_info->pass_by_reference = pass_by_reference;
cur_arg_info->class_name = NULL;
cur_arg_info->class_name_len = 0;

The entire parameter transfer is completed by performing an assignment operation to the arg_info field of the intermediate code. The key point is in the arg_info field. The structure of the arg_info field is as follows:

typedef struct _zend_arg_info {
    const char *name;   /*参数的名称*/
    zend_uint name_len;     /*参数名称的长度*/
    const char *class_name; /* 类名*/
     zend_uint class_name_len;   /*类名长度*/
    zend_bool array_type_hint;  /*数组类型提示*/
    zend_bool allow_null;   /*是否允许为NULLͺ*/
    zend_bool pass_by_reference;    /*是否引用传递*/
    zend_bool return_reference; 
    int required_num_args;  
} zend_arg_info;

The difference between parameter value passing and parameter passing is achieved through the pass_by_reference parameter when generating intermediate code.

Regarding the number of parameters, the arg_nums field contained in the intermediate code will be increased by 1 every time **zend_do_receive_argxx is executed. The following code:

CG(active_op_array)->num_args++;

And the index of the current parameter is CG( active_op_array)->num_args-1. The following code:

cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];

The above analysis is for the parameter settings when the function is defined, and these parameters are fixed. When actually writing a program, we may use variable parameters. At this time we will use the functions func_num_args and func_get_args. They exist as internal functions. So find the implementation of these two functions in the Zend\zend_builtin_functions.c file. Let’s first look at the implementation of the func_num_args function. The code is as follows:

/* {{{ proto int func_num_args(void)
   Get the number of arguments that were passed to the function */
ZEND_FUNCTION(func_num_args)
{
    zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
 
    if (ex && ex->function_state.arguments) {
        RETURN_LONG((long)(zend_uintptr_t)*(ex->function_state.arguments));
    } else {
        zend_error(E_WARNING,
"func_num_args():  Called from the global scope - no function context");
        RETURN_LONG(-1);
    }
}
/* }}} */

When ex->function_state.arguments exists and when the function is called, the converted value of ex->function_state.arguments is returned. , otherwise an error is displayed and -1 is returned. The most critical point here is EG (current_execute_data). This variable stores the data of the currently executing program or function. At this time, we need to get the data of the previous executing program. Why? Because the call of this function is executed after entering the function. The relevant data of the function are all in the previous execution process, so what is called is:

zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;

2. Parameters of the internal function

Taking the common count function as an example, the code for its parameter processing part As follows:

/* {{{ proto int count(mixed var [, int mode])
   Count the number of elements in a variable (usually an array) */
PHP_FUNCTION(count)
{
    zval *array;
    long mode = COUNT_NORMAL;
 
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l",
         &array, &mode) == FAILURE) {
        return;
    }
    ... //省略
}

This includes two operations: one is to get the number of parameters, and the other is to parse the parameter list.

(1) Get the number of parameters

The number of parameters is achieved through the ZEND_NUM_ARGS() macro, which is defined as follows:

#define ZEND_NUM_ARGS()     (ht)

ht is in Zend The ht in the macro INTERNAL_FUNCTION_PARAMETERS defined in the /zend.h file is as follows

#define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value,
zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC

(2) Parse parameter list

PHP internal functions use zend_parse_parameters when parsing parameters. It can greatly simplify the work of receiving and processing parameters, although it is still a bit weak when dealing with variable parameters.

Its declaration is as follows:

ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, 
...)

The first parameter num_args indicates the number of parameters you want to receive. We often use ZEND_NUM_ARGS() to express "as many parameters as you want" for the incoming parameters. ”

The second parameter should be the macro TSRMLS_CC.

The third parameter type_spec is a string used to specify the type of each parameter we expect to receive, somewhat similar to the formatting string that specifies the output format in printf.

The remaining parameters are pointers to the variables we use to receive PHP parameter values.

zend_parse_parameters() converts parameter types as much as possible while parsing parameters, so as to ensure that we can always get variables of the expected type

The above is the detailed content of In-depth understanding of parameter passing of PHP custom functions. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn