<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>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 6.2 引用與函數的執行結果 # 6.2 引用與函數的執行結果 一個函數的執行結果要返回給調用者,除了使用return功能,還有一種辦法,那就是以引用的形式傳遞參數,然后在內部修改這個參數的值。前一種方法往往只能返回一個值,如果我們的函數執行結果具有多種數據,便需要把這些數據打包到一個數組、類等復合類型的變量中才能得以實現;但后一種方法相比而言就簡單一些了。 ### 運行時傳遞引用:Call-time Pass-by-ref 標題有點繞口,其實很簡單,功能如以下php代碼所示: ``` <?php function byref_calltime($a) { $a = '(modified by ref!)'; } $foo = 'I am a string'; //使用&傳遞引用 byref_calltime(&$foo); echo $foo; //輸出'(modified by ref!)' ``` 我們在傳遞參數的時候使用&操作符,便可以傳遞$foo變量的引用過去,而不是copy一份。當我們在函數內核修改這個參數時,函數外部的$foo也跟著被一起修改了。同樣的功能我們如何在擴展里實現呢,其實很簡單,請看下面的源碼: ``` ZEND_FUNCTION(byref_calltime) { zval *a; //將我們接收的參數傳給zval *a; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a) == FAILURE) { RETURN_NULL(); } //如果a不是以引用的方式傳遞的。 if (!a->is_ref__gc) { return; } //將a轉成字符串 convert_to_string(a); //更改數據 ZVAL_STRING(a," (modified by ref!)",1); return; } ``` ### 編譯時的傳遞引用Compile-time Pass-by-ref 如果每一次都在調用函數時候都對參數加一個&符號真是太羅嗦了,有沒有一個簡單的辦法呢,比如在定義函數的時候便聲明這個參數是引用形式的,而不用用戶自己加&符號表示引用,而由內核來完成這步操作?這個功能是有的,我們在PHP語言中可以這樣實現。 ``` <?php 在定義函數參數的時候加了引用符 function byref_compiletime(&$a) { $a = ' (modified by ref!)'; } $foo = 'I am a string'; //這個地方我們沒有加&引用符 byref_compiletime($foo); echo $foo; //輸出 (modified by ref!) ``` 上面的代碼中,我們只是把引用符號從函數調用里轉移到函數定義里。此功能在擴展里面實現的話就頗費周折了,我們需要提前為它定義一個arginfo結構體來向內核通知此函數的這個特定行為。添加此函數到module\_entry里需要這樣: ``` ZEND_FE(byref_compiletime, byref_compiletime_arginfo) ``` byref\_compiletime\_arginfo是一個arginfo結構體,我們在前面的章節中已經用過一次了。 原書中此處有arginfo在PHP4里的實現,被我略去了。 在Zend Engine 2 (PHP5+)中,arginfo的數據是由多個zend\_arg\_info結構體構成的數組,數組的每一個成員即每一個zend\_arg\_info結構體處理函數的一個參數。zend\_arg\_info結構體的定義如下: ``` typedef struct _zend_arg_info { const char *name; /* 參數的名稱*/ zend_uint name_len; /* 參數名稱的長度*/ const char *class_name; /* 類名 */ zend_uint class_name_len; /* 類名長度*/ zend_bool array_type_hint; /* 數組類型提示 */ zend_bool allow_null; /* 是否允許為NULL */ zend_bool pass_by_reference; /* 是否引用傳遞 */ zend_bool return_reference; /* 返回值是否為引用形式 */ int required_num_args; /* 必要參數的數量 */ } zend_arg_info; ``` 生成zend\_arg\_info結構的數組比較繁瑣,為了方便PHP擴展開發者,內核已經準備好了相應的宏來專門處理此問題,首先先用一個宏函數來生成頭部,然后用第二個宏生成具體的數據,最后用一個宏生成尾部代碼。 ``` #define ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference) ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, ZEND_RETURN_VALUE, -1) #define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \ static const zend_arg_info name[] = { \ { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args }, #define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 }, #define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, NULL, 0, 0, 0, pass_by_ref, 0, 0 }, #define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, 0, allow_null, pass_by_ref, 0, 0 }, #define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, 1, allow_null, pass_by_ref, 0, 0 }, #define ZEND_END_ARG_INFO() }; //這里我們先看 ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference) ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference,required_num_args) ``` 這兩個宏函數的前兩個參數的含義是一樣的,name便是這個zend\_arg\_info數組變量的名字,這里我們定義它為:byref\_compiletime\_arginfo。pass\_rest\_by\_reference如果被賦值為1,則代表著所有的參數默認都是需要以引用的方式傳遞的(在arginfo中單獨聲明的除外)。而對于ZEND\_BEGIN\_ARG\_INFO\_EX的后兩個參數: - name和pass\_rest\_by\_reference的含義同上。 - return\_reference:聲明這個函數的返回值需要以引用的形式返回,這個參數已經在前面章節用過了。 - required\_num\_args:函數被調用時,傳遞參數至少為前N個函數(也就是后面參數都有默認值),當設置為-1時,必須傳遞所有參數 接下來讓我們看生成具體數據的宏: ``` ZEND_ARG_PASS_INFO(by_ref) //強制所有參數使用引用的方式傳遞 ZEND_ARG_INFO(by_ref, name) //如果by_ref為1,則名稱為name的參數必須以引用的方式傳遞, ZEND_ARG_ARRAY_INFO(by_ref, name, allow_null) ZEND_ARG_OBJ_INFO(by_ref, name, classname, allow_null) 這兩個宏實現了類型綁定,也就是說我們在傳遞某個參數時,必須是數組類型或者某個類的實例。如果最后的參數為真,則除了綁定的數據類型,還可以傳遞一個NULL數據。 //我們組合起來使用: ZEND_BEGIN_ARG_INFO(byref_compiletime_arginfo, 0) ZEND_ARG_PASS_INFO(1) ZEND_END_ARG_INFO() ``` 為了使我們的擴展能夠兼容PHP4,還需要使用#ifdef進行特殊處理。 ``` #ifdef ZEND_ENGINE_2 ZEND_BEGIN_ARG_INFO(byref_compiletime_arginfo, 0) ZEND_ARG_PASS_INFO(1) ZEND_END_ARG_INFO() #else /* ZE 1 */ static unsigned char byref_compiletime_arginfo[] = { 1, BYREF_FORCE }; #endif ``` 我們copy一份ZEND\_FUNCTION(byref\_calltime)的實現,并重名成ZEND\_FUNCTION(byref\_compiletime)就行了。或者直接弄個ZEND\_FALIAS就行了: ``` ZEND_FALIAS(byref_compiletime,byref_calltime,byref_compiletime_arginfo) ``` ## links - 6.1 [一個特殊的參數:return\_value](6.1.html) - 6.3 [第六章小結](6.3.html)
                  <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>

                              哎呀哎呀视频在线观看