php7扩展开发之调用用户自定义函数,使用可变参
假设php中的函数原型:
function calltask(callable $func[, mixed $arg1[, ...]]);
第一个参数是必须的,表示函数名,其他参数是可选参数。
扩展中的实现方式:
/* proto function calltask(callable $func[, mixed $arg1[, ...]]);*/
PHP_FUNCTION(calltask)
{
int i, status, argc = ZEND_NUM_ARGS();
zval *args = NULL;
zval retval;
// use FAST_ZPP get any count of args, args use original args pointer, no need to free here
#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
RETURN_FALSE;
}
#else
ZEND_PARSE_PARAMETERS_START(1, -1)
Z_PARAM_VARIADIC('+', args, argc)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
#endif
if (argc < 1) {
WRONG_PARAM_COUNT;
}
// 第一个参数为函数名 取出来
zval *thefunc = &(args[0]);
php_printf("you will call: %s argc=%d is_callable=%d\n", Z_STRVAL(*thefunc), argc, zend_is_callable(thefunc, IS_CALLABLE_CHECK_NO_ACCESS, NULL));
if (!zend_is_callable(thefunc, IS_CALLABLE_CHECK_NO_ACCESS, NULL)) {
php_printf("the function is not callable:%s\n", Z_STRVAL(*thefunc));
RETURN_FALSE;
}
// 从第二个参数开始,把参数打印出来
for (i=1; i<argc; i++) {
convert_to_string_ex(&args[i]);
php_printf("arg[%d] type=%d len=%d val=%s \n", i, Z_TYPE(args[i]), Z_STRLEN(args[i]), Z_STRVAL(args[i]));
}
// 使用zend_API.h中的call_user_function_ex调用
status = call_user_function_ex(EG(function_table), NULL, thefunc, &retval, argc-1, (argc>1?args+1:NULL), 0, NULL);
// 判断返回值
if (status == SUCCESS && !Z_ISUNDEF(retval)) {
php_printf("the function success:%d\n", status);
//zval_ptr_dtor(return_value);
//ZVAL_COPY_VALUE(return_value, &retval);
} else {
php_printf("the function failed:%d\n", status);
//zval_ptr_dtor(return_value);
//ZVAL_NULL(return_value);
}
php_printf("the call over: %s argc=%d status=%d\n", Z_STRVAL(*thefunc), argc);
//efree(args);// Z_PARAM_VARIADIC 的args指针来自于复制函数原参数指针,不需要free
RETURN_ZVAL(&retval, 1, 1);//RETURN_TRUE;// 返回该返回值的类型
}
zend_API.h中call_user_function的原型是:
ZEND_API int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[]);
ZEND_API int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], int no_separation, zend_array *symbol_table);