PHP扩展开发(6):接收参数

   

函数的参数则是PHP代码层和C代码层之间交换数据的唯一途径,因为PHP的调用语法是动态的,不会做任何错误检查,所以检查参数工作需要交给开发PHP扩展人员完成,看一下我们在快速入门里面的一段代码,使用zend_parse_parameters来解析参数:

PHP_FUNCTION(say_goodbye)
{
char *arg = NULL;
int arg_len, len;
char *strg;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
return;
}

len = spprintf(&strg, 0, "Goodbye %s\n", arg);
RETURN_STRINGL(strg, len, 0);
}

获取参数数量

PHP无法根据函数的显式声明来对调用进行语法检查,而且它还支持可变参数,所以我们就不得不在所调用函数的内部来获取参数个数。我们可以使用宏ZEND_NUM_ARGS来获取参数个数,如下面的代码:

if(ZEND_NUM_ARGS() != 2)
{
WRONG_PARAM_COUNT
}

这段代码使用宏WRONG_PARAM_COUNT抛出一个参数个数错误。

解析参数

开发PHP扩展时,解析参数基本是使用标准方式zend_parse_parameters,使用方式如下所示:

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

num_args参数指定参数个数,前面介绍过使用ZEND_NUM_ARGS获取参数个数;TSRMLS_DC宏指定线程安 全;type_spec参数是一个字符串,指定各个参数的类型,每个参数类型用一个字母表示。如果成功地解析和接收到了参数并且在转换期间也没出现错误, 那么这个函数就会返回SUCCESS,否则返回FAILURE,各个参数类型的字母标识如下:

l - 长整数
d - 双精度浮点数
s - 字符串 (也可能是空字节)和其长度
b - 布尔值
r - 资源, 保存在 zval*
a - 数组, 保存在 zval*
o - (任何类的)对象, 保存在 zval*
O - (由class entry 指定的类的)对象, 保存在 zval*
z - 实际的 zval*

在设置参数类型时,还可以使用以下几个特殊的字符:

| - 表明剩下的参数都是可选参数。如果用户没有传进来这些参数值,那么这些值就会被初始化成默认值。
/ - 表明参数解析函数将会对剩下的参数以 SEPARATE_ZVAL_IF_NOT_REF() 的方式来提供这个参数的一份拷贝,除非这些参数是一个引用。
! - 表明剩下的参数允许被设定为 NULL(仅用在 a、o、O、r和z身上)。如果用户传进来了一个 NULL 值,则存储该参数的变量将会设置为 NULL。

看看官方文档中提供的几个例子:


long l;
char *s;
int s_len;
zval *param;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lsz", &l, &s, &s_len, &param) == FAILURE) {
return;
}


zval *obj;
double d = 0.5;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|d", &obj, my_ce, &d) == FAILURE) {
return;
}


zval *obj;
zval *arr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O!a", &obj, &arr) == FAILURE) {
return;
}


zval *arr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &arr) == FAILURE) {
return;
}


zval *z;
zend_bool b;
zval *r;
if (zend_parse_parameters(3, "zbr!", &z, &b, &r) == FAILURE) {
return;
}

在接收参数时还有一个可用的函数zend_parse_parameters_ex,允许我们传入一些flags来控制解析参数的动作,使用方式如下所示:

int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...);

目前flags仅能传入ZEND_PARSE_PARAMS_QUIET这个值,表示函数不输出任何错误信息,如下面的示例:

long l1, l2, l3;
char *s;

if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC,
"lll", &l1, &l2, &l3) == SUCCESS) {

} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS(), "s", &s, &s_len) == SUCCESS) {

} else {
php_error(E_WARNING, "%s() takes either three long values or a string as argument",
get_active_function_name(TSRMLS_C));
return;
}

可变参数

由于PHP支持可变参数,所以在接收可变参数时,使用前面介绍的两个方法就不太合适,我们可以用zend_get_parameters_array_ex()来代替,如下面的示例:

zval **parameter_array[4];


argument_count = ZEND_NUM_ARGS();


if(argument_count < 2 || argument_count > 4)
{
WRONG_PARAM_COUNT;
}


if(zend_get_parameters_array_ex(argument_count, parameter_array) != SUCCESS)
{
WRONG_PARAM_COUNT;
}

本文我们介绍了在PHP扩展中接收参数,总共有三个函数:zend_parse_parameters、zend_parse_parameters_ex、zend_get_parameters_array_ex,关于参数解析其实还有更复杂的内容,下篇再介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值