深入PHP内核之函数和返回值

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)
{
}

参数解释

INTERNAL_FUNCTION_PARAMETERS
名称和类型描述访问宏
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)

 

posted @ 2015-08-05 21:28  踏雪无痕SS  阅读(837)  评论(0编辑  收藏  举报