调用内部函数时其返回值指针作为参数传入,这个参数为zval *return_value
,如果函数有返回值直接设置此指针即可,需要特别注意的是设置返回值时需要增加其引用计数,举个例子来看:
PHP_FUNCTION(my_func_1)
{
zval *arr;
if(zend_parse_parameters(ZEND_NUM_ARGS(), "a", &arr) == FAILURE){
RETURN_FALSE;
}
//增加引用计数
Z_ADDREF_P(arr);
//设置返回值为数组:
//return_value->u1.type = IS_ARRAY;
//return_value->value->arr = arr->value->arr;
ZVAL_ARR(return_value, Z_ARR_P(arr));
}
此函数接收一个数组,然后直接返回该数组,相当于:
function my_func_1($arr){
return $arr;
}
调用该函数:
$a = array(); //$a -> zend_array(refcount:1)
$b = my_func_1($a); //传参后:参数arr -> zend_array(refcount:2)
//然后函数内部赋给了返回值:$b,$a,arr -> zend_array(refcount:3)
//函数return阶段释放了参数:$b,$a -> zend_array(refcount:2)
var_dump($b);
=============[output]===========
array(0) {
}
虽然可以直接设置return_value,但实际使用时并不建议这么做,因为PHP提供了很多专门用于设置返回值的宏,这些宏定义在zend_API.h
中:
//返回布尔型,b:IS_FALSE、IS_TRUE
#define RETURN_BOOL(b) { RETVAL_BOOL(b); return; }
//返回NULL
#define RETURN_NULL() { RETVAL_NULL(); return;}
//返回整形,l类型:zend_long
#define RETURN_LONG(l) { RETVAL_LONG(l); return; }
//返回浮点值,d类型:double
#define RETURN_DOUBLE(d) { RETVAL_DOUBLE(d); return; }
//返回字符串,可返回内部字符串,s类型为:zend_string *
#define RETURN_STR(s) { RETVAL_STR(s); return; }
//返回内部字符串,这种变量将不会被回收,s类型为:zend_string *
#define RETURN_INTERNED_STR(s) { RETVAL_INTERNED_STR(s); return; }
//返回普通字符串,非内部字符串,s类型为:zend_string *
#define RETURN_NEW_STR(s) { RETVAL_NEW_STR(s); return; }
//拷贝字符串用于返回,这个会自己加引用计数,s类型为:zend_string *
#define RETURN_STR_COPY(s) { RETVAL_STR_COPY(s); return; }
//返回char *类型的字符串,s类型为char *
#define RETURN_STRING(s) { RETVAL_STRING(s); return; }
//返回char *类型的字符串,s类型为char *,l为字符串长度,类型为size_t
#define RETURN_STRINGL(s, l) { RETVAL_STRINGL(s, l); return; }
//返回空字符串
#define RETURN_EMPTY_STRING() { RETVAL_EMPTY_STRING(); return; }
//返回资源,r类型:zend_resource *
#define RETURN_RES(r) { RETVAL_RES(r); return; }
//返回数组,r类型:zend_array *
#define RETURN_ARR(r) { RETVAL_ARR(r); return; }
//返回对象,r类型:zend_object *
#define RETURN_OBJ(r) { RETVAL_OBJ(r); return; }
//返回zval
#define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
//返回false
#define RETURN_FALSE { RETVAL_FALSE; return; }
//返回true
#define RETURN_TRUE { RETVAL_TRUE; return; }