call_user_function

扩展可能需要调用用户自定义的函数或者其他扩展定义的内部函数,PHP提供的函数调用API的使用:



ZEND_API int call_user_function(HashTable *function_table, zval *object,zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[
]);
各参数的含义:



function_table: 函数符号表,普通函数是EG(function_table),如果是成员方法则是zend_class_entry.function_table
object: 调用成员方法时的对象
function_name: 调用的函数名称
retval_ptr: 函数返回值地址
param_count: 参数数量
params: 参数数组
从接口的定义看其使用还是很简单的,不需要我们关心执行过程中各阶段复杂的操作。



下面从一个具体的例子看下其使用:



(1)在PHP中定义了一个普通的函数,将参数$i加上100后返回:



function mySum($i){
return $i+100;
}



(2)接下来在扩展中调用这个函数:



PHP_FUNCTION(my_func_2)
{
    zend_long i;
    zval call_func_name, call_func_ret, call_func_params[1];
    uint32_t call_func_param_cnt = 1;
    zend_string *call_func_str;
    char *func_name = “mySum”;
    if(zend_parse_parameters(ZEND_NUM_ARGS(), “l”, &i) == FAILURE){
        RETURN_FALSE;
    }
    //分配zend_string:调用完需要释放
    call_func_str = zend_string_init(func_name, strlen(func_name), 0);
    //设置到zval
    ZVAL_STR(&call_func_name, call_func_str);
    
    //设置参数
    ZVAL_LONG(&call_func_params[0], i);
    
    //call
    if(SUCCESS != call_user_function(EG(function_table), NULL, &call_func_name, &call_func_ret, call_func_param_cnt, call_func_params)){
        zend_string_release(call_func_str);
        RETURN_FALSE;
    }
    
    zend_string_release(call_func_str);
    RETURN_LONG(Z_LVAL(call_func_ret));
}
(3)最后调用这个内部函数:



function mySum($i){
return $i+100;
}
echo my_func_2(60);
===========[output]===========
160
call_user_function() 并不是只能调用PHP脚本中定义的函数,内核或其它扩展注册
的函数同样可以通过此函数调用,比如:array_merge()。



PHP_FUNCTION(my_func_1)
{
    zend_array *arr1, *arr2;
    zval call_func_name, call_func_ret, call_func_params[2];
    uint32_t call_func_param_cnt = 2;
    zend_string *call_func_str;
    char *func_name = “array_merge”;
    if(zend_parse_parameters(ZEND_NUM_ARGS(), “hh”, &arr1, &arr2) == FAILURE){
        RETURN_FALSE;
    }
    
    //分配zend_string
    call_func_str = zend_string_init(func_name, strlen(func_name), 0);
    //设置到zval
    ZVAL_STR(&call_func_name, call_func_str);
    
    ZVAL_ARR(&call_func_params[0], arr1);
    ZVAL_ARR(&call_func_params[1], arr2);
    
    if(SUCCESS != call_user_function(EG(function_table), NULL, &call_func_name, &call_func_ret, call_func_param_cnt, call_func_params)){
    zend_string_release(call_func_str);
    RETURN_FALSE;
    }
    zend_string_release(call_func_str);
    RETURN_ARR(Z_ARRVAL(call_func_ret));
}
$arr1 = array(1,2);
$arr2 = array(3,4);
$arr = my_func_1($arr1, $arr2);
var_dump($arr);



https://blog.csdn.net/rorntuck7/article/details/86240202


Category php