<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ### 7.6.3 引用傳參 上一節介紹了如何在內部函數中解析參數,這里還有一種情況沒有講到,那就是引用傳參: ```php $a = array(); function my_func(&$a){ $a[] = 1; } ``` 上面這個例子在函數中對$a的修改將反映到原變量上,那么這種用法如何在內部函數中實現呢?上一節介紹參數解析的過程中并沒有提到用戶函數中參數的zend_arg_info結構,內部函數中也有類似的一個結構用于函數注冊時指定參數的一些信息:zend_internal_arg_info。 ```c typedef struct _zend_internal_arg_info { const char *name; //參數名 const char *class_name; zend_uchar type_hint; //顯式聲明的類型 zend_uchar pass_by_reference; //是否引用傳參 zend_bool allow_null; //是否允許參數為NULL,類似"!"的用法 zend_bool is_variadic; //是否為可變參數 } zend_internal_arg_info; ``` 這個結構幾乎與zend_arg_info完全一樣,不同的地方只在于name、class_name的類型,zend_arg_info這兩個成員的類型都是zend_string。如果函數需要使用引用類型的參數或返回引用就需要創建函數的參數數組,這個數組通過:`ZEND_BEGIN_ARG_INFO()或ZEND_BEGIN_ARG_INFO_EX()`、`ZEND_END_ARG_INFO()`宏定義: ```c #define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) #define ZEND_BEGIN_ARG_INFO(name, _unused) ``` * __name:__ 參數數組名,注冊函數`PHP_FE(function, arg_info)`會用到 * ___unused:__ 保留值,暫時無用 * __return_reference:__ 返回值是否為引用,一般很少會用到 * __required_num_args:__ required參數數 這兩個宏需要與`ZEND_END_ARG_INFO()`配合使用: ```c ZEND_BEGIN_ARG_INFO_EX(arginfo_my_func_1, 0, 0, 2) ... ZEND_END_ARG_INFO() ``` 接著就是在上面兩個宏中間定義每一個參數的zend_internal_arg_info,PHP提供的宏有: ```c //pass_by_ref表示是否引用傳參,name為參數名稱 #define ZEND_ARG_INFO(pass_by_ref, name) { #name, NULL, 0, pass_by_ref, 0, 0 }, //只聲明此參數為引用傳參 #define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, NULL, 0, pass_by_ref, 0, 0 }, //顯式聲明此參數的類型為指定類的對象,等價于PHP中這樣聲明:MyClass $obj #define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, #classname, IS_OBJECT, pass_by_ref, allow_null, 0 }, //顯式聲明此參數類型為數組,等價于:array $arr #define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, NULL, IS_ARRAY, pass_by_ref, allow_null, 0 }, //顯式聲明為callable,將檢查函數、成員方法是否可調 #define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) { #name, NULL, IS_CALLABLE, pass_by_ref, allow_null, 0 }, //通用宏,自定義各個字段 #define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, NULL, type_hint, pass_by_ref, allow_null, 0 }, //聲明為可變參數 #define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) { #name, NULL, 0, pass_by_ref, 0, 1 }, ``` 舉個例子來看: ```php function my_func_1(&$a, Exception $c){ ... } ``` 用內核實現則可以這么定義: ```c ZEND_BEGIN_ARG_INFO_EX(arginfo_my_func_1, 0, 0, 1) ZEND_ARG_INFO(1, a) //引用 ZEND_ARG_OBJ_INFO(0, b, Exception, 0) //注意:這里不要把字符串加"" ZEND_END_ARG_INFO() ``` 展開后: ```c static const zend_internal_arg_info name[] = { //多出來的這個是給返回值用的 { (const char*)(zend_uintptr_t)(2), NULL, 0, 0, 0, 0 }, { "a", NULL, 0, 0, 0, 0 }, { "b", "Exception", 8, 1, 0, 0 }, } ``` 第一個數組元素用于記錄必傳參數的數量以及返回值是否為引用。定義完這個數組接下來就需要把這個數組告訴函數: ```c const zend_function_entry mytest_functions[] = { PHP_FE(my_func_1, arginfo_my_func_1) PHP_FE(my_func_2, NULL) PHP_FE_END //末尾必須加這個 }; ``` 引用參數通過`zend_parse_parameters()`解析時只能使用"z"解析,不能再直接解析為zend_value了,否則引用將失效: ```c PHP_FUNCTION(my_func_1) { zval *lval; //必須為zval,定義為zend_long也能解析出,但不是引用 zval *obj; if(zend_parse_parameters(ZEND_NUM_ARGS(), "zo", &lval, &obj) == FAILURE){ RETURN_FALSE; } //lval的類型為IS_REFERENCE zval *real_val = Z_REFVAL_P(lval); //獲取實際引用的zval地址:&(lval.value->ref.val) Z_LVAL_P(real_val) = 100; //設置實際引用的類型 } ``` ```php $a = 90; $b = new Exception; my_func_1($a, $b); echo $a; ==========[output]=========== 100 ``` > __Note:__ 參數數組與zend_parse_parameters()有很多功能重合,兩者都會生效,對zend_internal_arg_info驗證在zend_parse_parameters()之前,為避免混亂兩者應該保持一致;另外,雖然內部函數的參數數組并不強制定義聲明,但還是建議聲明。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看