• 深入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)
    
  • 相关阅读:
    Spring Cloud Bus 消息总线介绍
    工商银行分布式服务 C10K 场景解决方案
    关于写好文章的3个心法和5点技巧
    混合云K8s容器化应用弹性伸缩实战
    云原生下的灰度体系建设
    被解救的代码
    【2020-10-22】我是否一个真正靠谱的人
    【2020-10-21】以谦虚与忍耐去期待豁然与贯通
    【2020-10-20】压力也是一种感受,用心体会
    【2020-10-19】不断试错的过程
  • 原文地址:https://www.cnblogs.com/chenpingzhao/p/4705900.html
Copyright © 2020-2023  润新知