[李景山php] 深入理解PHP内核[读书笔记]--第四章:函数的实现 --函数的参数

49 篇文章 0 订阅

函数的参数


上回书说到:函数的定义是一个将函数名注册到函数列表的过程。
函数的参数检查是通过zend_do_receive_arg函数实现的。

用户自定义函数的参数


在zend_do_receive_arg函数中对于参数的关键代码如下:

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;

整个参数的传递是通过给中间代码的arg_info字段执行赋值操作完成。关键点是在arg_info字段。
字段的结构如下:

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;

参数的值传递和参数传递的区分是通过pass_by_reference参数在生成中间代码时实现的。

在实际编程中我们可能会遇到可变参数。

func_num_args;
func_get_args;

其中 func_num_args的内部实现如下:
位于 Zend/zend_builtin_functions.c文件中

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_uinptr_t)*(ex->function_state.arguments)); 
     }else{
         zend_error(E_WARNING,"func_num_args(); called from the global scope no function context");
          RETURN_LONG(-1); 
     }
}

另外的一个函数也是一样的。关键在于在 current_execute_data 进行执行。

内部函数的参数


PHP_FUNCTION(count)
{
     zval *array;
     long mode = COUNT_NORMAL;

     if(zend_parse_parameters(ZEND_NUM_ARGSS) TSRMLS_CC,"z|l", &array,&node) == FAILURE){
          return ;
     }
}

两个关键点:
一个是取参数的个数,一个是解析参数列表。

取参数的个数是通过ZEND_NUM_ARGS()宏来实现。
\#define ZEND_NUM_ARGS()     (ht)

ht是在 Zend/zend.h文件中定义的宏 INTERNAL_FUNCTION_PARAMETERS中的ht,如下:

解析参数列表

php内部函数在解析参数时使用的是zend_parse_parameters.它可以大大简化参数的接收处理工作,虽然它在处理可变参数时还有点弱。

其声明如下:

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

第一个参数:num_args表明示想要接收的参数个数,我们经常使用ZEND_NUM_ARGS()来表示对传入的参数”有多少要多少”
第二个参数:是宏TSRMLS_CC.
第三个参数:type_spec是一个字符串,用来指定我们所期待接收的各个参数的类型,有点类似于printf中指定输出格式的那个格式化字符串。
剩下的参数就是我们用来接收PHP参数值的变量指针。

参数的传递


function do_something($s){
     xdebug_debug_zval('s');
     $s = 100;
     return $s;
}

$a = 1111;
$b = do_something($a);
echo $b;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值