1、关于返回值,PHP内核中使用了大量的宏来实现,我们先看一个函数
PHP_FUNCTION 宏的定义(Zend/zend_API.h)
#define PHP_FUNCTION ZEND_FUNCTION #define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name)) #define ZEND_FN(name) zif_##name #define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS) #define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC //最终 void zif_hello_world(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC) { }
参数解释
名称和类型 | 描述 | 访问宏 |
---|---|---|
int ht |
用户实际传递参数的数量 | ZEND_NUM_ARGS() |
zval *return_value |
PHP 变量的指针,可填充返回值传递给用户。默认值是 IS_NULL 。 |
RETVAL_* , RETURN_* |
zval **return_value_ptr |
当返回引用时,PHP 将其设为变量的指针。不建议返回引用。 | |
zval *this_ptr |
假如这是一个方法调用,其指向存放 $this 对象的 PHP 变量。 |
getThis() |
int return_value_used |
指示返回值是否会被调用者使用的标志。 caller. |
函数入口可含有一个对参数信息结构的指针。 不是必须要提供此信息,除非打算接受参数引用或返回一个引用,及提供由 PHP 的反射 API 访问的信息。参数可以直接作为函数参数传递,也可以是通过一个堆栈(stack)
2、用于返回值的宏
a)RETURN_BOOL(0); //返回bool值
#define RETVAL_BOOL(b) ZVAL_BOOL(return_value, b) #define RETURN_BOOL(b) { RETVAL_BOOL(b); return; } #define ZVAL_BOOL(z, b) do { zval *__z = (z); Z_LVAL_P(__z) = ((b) != 0); Z_TYPE_P(__z) = IS_BOOL; } while (0)
所以展开这个RETURN_BOOL(0),最终在函数里返回值的操作即是
do { zval *__z = (return_value); Z_LVAL_P(__z) = ((0) != 0); //定义return_value值 Z_TYPE_P(__z) = IS_BOOL; //定义return_value的类型 }while(0)
b) RETURN_STRING("hello world", 1);
展开之后
do { const char *__s = ("hello world"); zval *__z = return_value; Z_STRLEN_P(__z) = strlen(__s);//定义长度 Z_STRVAL_P(__z) = (1?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);//定义值,estrndup函数实现字符串的复制 Z_TYPE_P(__z) = IS_STRING; }while(0)
c) RETURN_LONG(100);
展开之后
zval *__z = return_value; Z_LVAL_P(__z) = 100; Z_TYPE_P(__z) = IS_LONG;
d)返回数组
array_init(return_value);//初始化return_value成数组,此操作完后就可以返回一个空的数组
e)返回object
object_init(return_value);//初始化return_value成Object,此操作完成后返回一个空的对像
其他的
#define ZVAL_FALSE(z) ZVAL_BOOL(z, 0) #define ZVAL_TRUE(z) ZVAL_BOOL(z, 1) #define RETVAL_RESOURCE(l) ZVAL_RESOURCE(return_value, l) #define RETVAL_BOOL(b) ZVAL_BOOL(return_value, b) #define RETVAL_NULL() ZVAL_NULL(return_value) #define RETVAL_LONG(l) ZVAL_LONG(return_value, l) #define RETVAL_DOUBLE(d) ZVAL_DOUBLE(return_value, d) #define RETVAL_STRING(s, duplicate) ZVAL_STRING(return_value, s, duplicate) #define RETVAL_STRINGL(s, l, duplicate) ZVAL_STRINGL(return_value, s, l, duplicate) #define RETVAL_EMPTY_STRING() ZVAL_EMPTY_STRING(return_value) #define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor) #define RETVAL_FALSE ZVAL_BOOL(return_value, 0) #define RETVAL_TRUE ZVAL_BOOL(return_value, 1) #define RETURN_RESOURCE(l) { RETVAL_RESOURCE(l); return; } #define RETURN_BOOL(b) { RETVAL_BOOL(b); return; } #define RETURN_NULL() { RETVAL_NULL(); return;} #define RETURN_LONG(l) { RETVAL_LONG(l); return; } #define RETURN_DOUBLE(d) { RETVAL_DOUBLE(d); return; } #define RETURN_STRING(s, duplicate) { RETVAL_STRING(s, duplicate); return; } #define RETURN_STRINGL(s, l, duplicate) { RETVAL_STRINGL(s, l, duplicate); return; } #define RETURN_EMPTY_STRING() { RETVAL_EMPTY_STRING(); return; } #define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; } #define RETURN_FALSE { RETVAL_FALSE; return; } #define RETURN_TRUE { RETVAL_TRUE; return; }
3、数组以及对象的操作
zval *arr; MAKE_STD_ZVAL(arr); array_init(arr); //$arr = array(); add_assoc_long(arr, "a", 10); //$arr["a"] = 10; add_asoc_unset(arr, "a"); //unset(arr["a"]); add_assoc_bool(arr, "b", 1); //$arr["b"] = true; add_assoc_resource(arr, "c", 10); //$arr["c"] = $resource; add_assoc_double(arr, "d", 2.15); //$arr["d"] = 2.15; add_assoc_string(arr, "e", "hello", 1); //$arr["e"] = "hello";最后一个参数表示字符串值是否复制 add_assoc_stringl(); zval *sub; MAKE_STD_ZVAL(sub); array_init(sub); add_assoc_zval(arr, "f", sub); //$arr["f"] = $sub; zval *arr; MAKE_STD_ZVAL(arr); array_init(arr); //$arr = array(); add_index_long(arr, 1, 10); //$arr[1] = 10; add_index_unset(arr, 1); //unset($arr[1]); add_index_bool(arr, 2, 1); //$arr[2] = true; add_index_resource(arr, 3, 10); //$arr[3] = $resource; add_index_double(arr, 4, 2.15); //$arr[4] = 2.15; add_index_string(arr, 5, "hello", 1); //$arr[5] = "hello";最后一个参数表示字符串值是否复制 add_index_stringl(); zval *sub; MAKE_STD_ZVAL(sub); array_init(sub); add_index_zval(arr, 6, sub); //$arr[6] = $sub; zval *arr; MAKE_STD_ZVAL(arr); array_init(arr); //$arr = array(); add_next_index_long(arr, 10); //$arr[] = 10; add_next_index_unset(arr); //unset($arr[]); add_next_index_bool(arr, 1); //$arr[] = true; add_next_index_resource(arr, 10); //$arr[] = $resource; add_next_index_double(arr, 2.15); //$arr[] = 2.15; add_next_index_string(arr, "hello", 1); //$arr[] = "hello";最后一个参数表示字符串值是否复制 add_next_index_stringl(); zval *sub; MAKE_STD_ZVAL(sub); array_init(sub); add_next_index_zval(arr, sub); //$arr[] = $sub; zval *obj; MAKE_STD_ZVAL(obj); object_init(obj);//$obj = new stdClass; add_property_long(obj, "a", 10); //$obj->a = 10; add_property_unset(obj, "a"); //unset($obj->a); add_property_bool(obj, "b", 1); //$obj->b = true; add_property_resource(obj, "c", 10); //$obj->c = $resource; add_property_double(obj, "d", 2.15); //$obj->d = 2.15; add_property_string(obj, "e", "hello", 1);//$obj->e = "hello"; 最后一个参数表示字符串值是否复制 add_property_stringl(); zval *sub; MAKE_STD_ZVAL(sub); object_init(sub); //$sub = new stdClass; add_property_zval(obj, "f", sub); //$obj->f = $sub;
一些操作的宏
#define Z_LVAL(zval) (zval).value.lval #define Z_BVAL(zval) ((zend_bool)(zval).value.lval) #define Z_DVAL(zval) (zval).value.dval #define Z_STRVAL(zval) (zval).value.str.val #define Z_STRLEN(zval) (zval).value.str.len #define Z_ARRVAL(zval) (zval).value.ht #define Z_OBJVAL(zval) (zval).value.obj #define Z_OBJ_HANDLE(zval) Z_OBJVAL(zval).handle #define Z_OBJ_HT(zval) Z_OBJVAL(zval).handlers #define Z_OBJCE(zval) zend_get_class_entry(&(zval) TSRMLS_CC) #define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC) #define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf #define Z_RESVAL(zval) (zval).value.lval #define Z_OBJDEBUG(zval,is_tmp) (Z_OBJ_HANDLER((zval), get_debug_info)?Z_OBJ_HANDLER((zval),get_debug_info)(&(zval), &is_tmp TSRMLS_CC):(is_tmp=0,Z_OBJ_HANDLER((zval),get_properties)?Z_OBJPROP(zval):NULL)) #define Z_LVAL_P(zval_p) Z_LVAL(*zval_p) #define Z_BVAL_P(zval_p) Z_BVAL(*zval_p) #define Z_DVAL_P(zval_p) Z_DVAL(*zval_p) #define Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p) #define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p) #define Z_ARRVAL_P(zval_p) Z_ARRVAL(*zval_p) #define Z_OBJPROP_P(zval_p) Z_OBJPROP(*zval_p) #define Z_OBJCE_P(zval_p) Z_OBJCE(*zval_p) #define Z_RESVAL_P(zval_p) Z_RESVAL(*zval_p) #define Z_OBJVAL_P(zval_p) Z_OBJVAL(*zval_p) #define Z_OBJ_HANDLE_P(zval_p) Z_OBJ_HANDLE(*zval_p) #define Z_OBJ_HT_P(zval_p) Z_OBJ_HT(*zval_p) #define Z_OBJ_HANDLER_P(zval_p, h) Z_OBJ_HANDLER(*zval_p, h) #define Z_OBJDEBUG_P(zval_p,is_tmp) Z_OBJDEBUG(*zval_p,is_tmp) #define Z_LVAL_PP(zval_pp) Z_LVAL(**zval_pp) #define Z_BVAL_PP(zval_pp) Z_BVAL(**zval_pp) #define Z_DVAL_PP(zval_pp) Z_DVAL(**zval_pp) #define Z_STRVAL_PP(zval_pp) Z_STRVAL(**zval_pp) #define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp) #define Z_ARRVAL_PP(zval_pp) Z_ARRVAL(**zval_pp) #define Z_OBJPROP_PP(zval_pp) Z_OBJPROP(**zval_pp) #define Z_OBJCE_PP(zval_pp) Z_OBJCE(**zval_pp) #define Z_RESVAL_PP(zval_pp) Z_RESVAL(**zval_pp) #define Z_OBJVAL_PP(zval_pp) Z_OBJVAL(**zval_pp) #define Z_OBJ_HANDLE_PP(zval_p) Z_OBJ_HANDLE(**zval_p) #define Z_OBJ_HT_PP(zval_p) Z_OBJ_HT(**zval_p) #define Z_OBJ_HANDLER_PP(zval_p, h) Z_OBJ_HANDLER(**zval_p, h) #define Z_OBJDEBUG_PP(zval_pp,is_tmp) Z_OBJDEBUG(**zval_pp,is_tmp) #define Z_TYPE(zval) (zval).type #define Z_TYPE_P(zval_p) Z_TYPE(*zval_p) #define Z_TYPE_PP(zval_pp) Z_TYPE(**zval_pp)