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

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ### 7.6.5 函數調用 實際應用中,擴展可能需要調用用戶自定義的函數或者其他擴展定義的內部函數,前面章節已經介紹過函數的執行過程,這里不再重復,本節只介紹下PHP提供的函數調用API的使用: ```c ZEND_API int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[]); ``` 各參數的含義: * __function_table:__ 函數符號表,普通函數是EG(function_table),如果是成員方法則是zend_class_entry.function_table * __object:__ 調用成員方法時的對象 * __function_name:__ 調用的函數名稱 * __retval_ptr:__ 函數返回值地址 * __param_count:__ 參數數量 * __params:__ 參數數組 從接口的定義看其使用還是很簡單的,不需要我們關心執行過程中各階段復雜的操作。下面從一個具體的例子看下其使用: (1)在PHP中定義了一個普通的函數,將參數$i加上100后返回: ```php function mySum($i){ return $i+100; } ``` (2)接下來在擴展中調用這個函數: ```c PHP_FUNCTION(my_func_1) { zend_long i; zval call_func_name, call_func_ret, call_func_params[1]; uint32_t call_func_param_cnt = 1; zend_string *call_func_str; char *func_name = "mySum"; if(zend_parse_parameters(ZEND_NUM_ARGS(), "l", &i) == FAILURE){ RETURN_FALSE; } //分配zend_string:調用完需要釋放 call_func_str = zend_string_init(func_name, strlen(func_name), 0); //設置到zval ZVAL_STR(&call_func_name, call_func_str); //設置參數 ZVAL_LONG(&call_func_params[0], i); //call if(SUCCESS != call_user_function(EG(function_table), NULL, &call_func_name, &call_func_ret, call_func_param_cnt, call_func_params)){ zend_string_release(call_func_str); RETURN_FALSE; } zend_string_release(call_func_str); RETURN_LONG(Z_LVAL(call_func_ret)); } ``` (3)最后調用這個內部函數: ```php function mySum($i){ return $i+100; } echo my_func_1(60); ===========[output]=========== 160 ``` `call_user_function()`并不是只能調用PHP腳本中定義的函數,內核或其它擴展注冊的函數同樣可以通過此函數調用,比如:array_merge()。 ```c PHP_FUNCTION(my_func_1) { zend_array *arr1, *arr2; zval call_func_name, call_func_ret, call_func_params[2]; uint32_t call_func_param_cnt = 2; zend_string *call_func_str; char *func_name = "array_merge"; if(zend_parse_parameters(ZEND_NUM_ARGS(), "hh", &arr1, &arr2) == FAILURE){ RETURN_FALSE; } //分配zend_string call_func_str = zend_string_init(func_name, strlen(func_name), 0); //設置到zval ZVAL_STR(&call_func_name, call_func_str); ZVAL_ARR(&call_func_params[0], arr1); ZVAL_ARR(&call_func_params[1], arr2); if(SUCCESS != call_user_function(EG(function_table), NULL, &call_func_name, &call_func_ret, call_func_param_cnt, call_func_params)){ zend_string_release(call_func_str); RETURN_FALSE; } zend_string_release(call_func_str); RETURN_ARR(Z_ARRVAL(call_func_ret)); } ``` ```php $arr1 = array(1,2); $arr2 = array(3,4); $arr = my_func_1($arr1, $arr2); var_dump($arr); ``` 你可能會注意到,上面的例子通過`call_user_function()`調用函數時并沒有增加兩個數組參數的引用計數,但根據前面介紹的內容:函數傳參時不會硬拷貝value,而是增加參數value的引用計數,然后在函數return階段再把引用減掉。實際是`call_user_function()`替我們完成了這個工作,下面簡單看下其處理過程。 ```c int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[]) { return call_user_function_ex(function_table, object, function_name, retval_ptr, param_count, params, 1, NULL); } int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], int no_separation, zend_array *symbol_table) { zend_fcall_info fci; fci.size = sizeof(fci); fci.function_table = function_table; fci.object = object ? Z_OBJ_P(object) : NULL; ZVAL_COPY_VALUE(&fci.function_name, function_name); fci.retval = retval_ptr; fci.param_count = param_count; fci.params = params; fci.no_separation = (zend_bool) no_separation; fci.symbol_table = symbol_table; return zend_call_function(&fci, NULL); } ``` `call_user_function()`將我們提供的參數組裝為`zend_fcall_info`結構,然后調用`zend_call_function()`進行處理,還記得`zend_parse_parameters()`那個"f"解析符嗎?它也是將輸入的函數名稱解析為一個`zend_fcall_info`,可以更方便的調用函數,同時我們也可以自己創建一個`zend_fcall_info`結構,然后使用`zend_call_function()`完成函數的調用。 ```c int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) { ... for (i=0; i<fci->param_count; i++) { zval *param; zval *arg = &fci->params[i]; ... //為參數添加引用 if (Z_OPT_REFCOUNTED_P(arg)) { Z_ADDREF_P(arg); } } ... //調用的是用戶函數 if (func->type == ZEND_USER_FUNCTION) { //執行 zend_init_execute_data(call, &func->op_array, fci->retval); zend_execute_ex(call); }else if (func->type == ZEND_INTERNAL_FUNCTION){ //內部函數 if (EXPECTED(zend_execute_internal == NULL)) { func->internal_function.handler(call, fci->retval); } else { zend_execute_internal(call, fci->retval); } } ... } ```
                  <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>

                              哎呀哎呀视频在线观看