在正常的開發思維裡,固有的返回值都應該是如下邏輯
Int a(){
Return 1;
}
然而,Php返回值是返回一個zval* 數據結構。
而且不能直接使用return操作,而是通過一個神奇的指針retuen_value 來存儲。看是沒有定義,其實不然。
這個神奇的retuen_value處理過程,先看正確的返回值操作
PHP_FUNCTION(hello)
{
ZVAL_STRING(return_value,“hello”, 1); //RETVAL_STRING(“hello”, 1);
Return ;
}
刨根問底,必須從 PHP_FUNCTION 這個定義開始,要習慣了PHP和ZEND 的關系
PHP還是一貫的重新命名zend 的宏
#define PHP_FUNCTION ZEND_FUNCTION
一路追蹤
#define ZEND_FN(name) zif_##name
#define ZEND_MN(name) zim_##name
#define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS)
#define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name))
#define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_MN(classname##_##name))
關鍵地方:
#define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS)
在 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
包括成員:
/*
等價與ZEND_NUM_ARGS() ,表示參數的個數
*/
int ht
/*
存儲值,關鍵是_zval_struct 數據結構
*/
zval *return_value
/*
引用地址
*/
zval **return_value_ptr,
/*
對象
*/
zval *this_ptr,
/*
表示是否返回值
*/
int return_value_used
下面在做個例子,演示下return_value_used 的作用
PHP_FUNCTION(retuen_value_used_test)
{
char *arg = NULL;
zval *a,*b,*c;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzz", &a,&b,&c) == FAILURE) {
return;
}
/*關鍵點*/
php_printf("%d",return_value_used);
RETURN_STRINGL(Z_STRVAL_P(a), Z_STRLEN_P(a), 0);
}
這是1個很簡單函數定義,實現傳入3個參數(我為了方便,直接定義成z類型)
PHP調用方法
<?php
retuen_value_used_test("2","v","dd");
?>
當PHP程序retuen_value_used_test函數沒有用到返回值的時候,結果是:
0
<?php
$log = retuen_value_used_test("2","v","dd");
?>
當PHP程序retuen_value_used_test函數使用到返回值的時候,結果是:
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)