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

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 起步 很多時候,需要把控制權限交給用戶,或者在擴展里完成某件事后去回調用戶的方法。 在PHP擴展里是通過 `call_user_function_ex` 函數來調用用戶空間的函數的。 ## 定義 它的定義在 [Zend/zend_API.h ](https://github.com/php/php-src/blob/master/Zend/zend_API.h): ```c #define call_user_function_ex(function_table, object, function_name, retval_ptr, param_count, params, no_separation, symbol_table) _call_user_function_ex(object, function_name, retval_ptr, param_count, params, no_separation) ``` 通過宏定義替換為_call_user_function_ex,其中參數 function_table 被移除了,它之所以在API才存在大概是為了兼容以前的寫法。函數的真正定義是: ```c ZEND_API int _call_user_function_ex( zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], int no_separation); ``` 參數分析: * `zval *object`:這個是用來我們調用類里的某個方法的對象。 * `zval *function_name`:要調用的函數的名字。 * `zval *retval_ptr`:收集回調函數的返回值。 * `uint32_t param_count`:回調函數需要傳遞參數的個數。 * `zval params[]`: 參數列表。 * `int no_separation`:是否對zval進行分離,如果設為1則直接會出錯,分離的作用是為了優化空間。 ## 回調功能的實現 ```c PHP_FUNCTION(hello_callback) { zval *function_name; zval retval; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &function_name) == FAILURE) { return; } if (Z_TYPE_P(function_name) != IS_STRING) { php_printf("Function require string argumnets!"); return; } //TSRMLS_FETCH(); if (call_user_function_ex(EG(function_table), NULL, function_name, &retval, 0, NULL, 0, NULL TSRMLS_CC) != SUCCESS) { php_printf("Function call failed!"); return; } *return_value = retval; zval_copy_ctor(return_value); zval_ptr_dtor(&retval); } ``` `zval_copy_ctor()`原始(zval)的內容拷貝給它。`zval_ptr_dtor()`釋放空間。`return_value`不是一個函數外的變量,它的由函數聲明里的變量。`PHP_FUNCTION(hello_callback)`這個聲明是簡寫,最終會被預處理宏替換為: ``` void zif_hello_callback(zend_execute_data *execute_data, zval *return_value) ``` `return_value`變量其實也就是最終返回給調用腳本的,RETURN_STR(s) 等返回函數最終也都是宏替換為對該變量的操作。 測試腳本: ``` <?php function fun1() { for ($i = 0; $i < 5; $i++) { echo 'fun1:'.$i."\n"; } return 'call end'; } echo hello_callback('fun1'); ``` ## 一個并行擴展 早期的php不支持多進程多線程的,現在隨著發展有很多擴展不斷完善它,諸如`pthread`,`swoole`等,不僅能多線程,而且能實現異步。 利用c語言多線程`pthread`庫來實現一個簡單的并行擴展。 先聲明我們一會用到的結構: ``` struct myarg { zval *fun; zval ret; }; ``` 線程函數: ``` static void my_thread(struct myarg *arg) { zval *fun = arg->fun; zval ret = arg->ret; if (call_user_function_ex(EG(function_table), NULL, fun, &ret, 0, NULL, 0, NULL TSRMLS_CC) != SUCCESS) { return; } } ``` 函數的實現: ``` PHP_FUNCTION(hello_thread) { pthread_t tid; zval *fun1, *fun2; zval ret1, ret2; struct myarg arg; int ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &fun1, &fun2) == FAILURE) { return; } arg.fun = fun1; arg.ret = ret1; ret = pthread_create(&tid, NULL, (void*)my_thread, (void*)&arg); if(ret != 0) { php_printf("Thread Create Error\n"); exit(0); } if (call_user_function_ex(EG(function_table), NULL, fun2, &ret2, 0, NULL, 0, NULL TSRMLS_CC) != SUCCESS) { return; } pthread_join(tid, NULL); RETURN_NULL(); } ``` 測試腳本: ``` <?php function fun1() { for ($i = 0; $i < 5; $i++) { echo 'fun1:'.$i.'\n'; } } function fun2() { for ($i = 0; $i < 5; $i++) { echo 'fun2:'.$i.'\n'; } } hello_thread('fun1', 'fun2'); echo 'after 多并發'; ``` 輸出: ![](https://box.kancloud.cn/d491f07e3c3eae74403708f3880c6d47_540x350.png) 兩次的輸出結果不一樣,并且`echo 'after 多并發';`是在兩個函數都運行完后才執行的。
                  <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>

                              哎呀哎呀视频在线观看