<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之旅 廣告
                [TOC] 某個功能被編譯到so文件中,那么如何通過php來調用它?一個方法是寫一個php模塊(php extension),在php中調用該模塊內的函數,再通過該模塊來調用so中的函數。下面做一個簡單的例子,使用的操作系統是RHEL5。 ### 制作.so文件 #### 首先做一個簡單的so文件: /** * hello.c * To compile, use following commands: * gcc -O -c -fPIC -o hello.o hello.c * gcc -shared -o libhello.so hello.o */ int hello_add(int a, int b) { return a + b; } #### 然后將它編譯成.so文件并放到系統中: ``` $ gcc -O -c -fPIC -o hello.o hello.c $ gcc -shared -o libhello.so hello.o $ su # echo /usr/local/lib > /etc/ld.so.conf.d/local.conf # cp libhello.so /usr/local/lib # /sbin/ldconfig ``` #### 寫段小程序來驗證其正確性: ``` /** * hellotest.c * To compile, use following commands: * gcc -o hellotest -lhello hellotest.c */ #i nclude <stdio.h> int main() { int a = 3, b = 4; printf("%d + %d = %d/n", a, b, hello_add(a,b)); return 0; } ``` #### 編譯并執行: ``` $ gcc -o hellotest -lhello hellotest.c $ ./hellotest 3 + 4 = 7 ``` ### 為php添加擴展 #### 通過下面的命令建立一個名為 hello 的模塊。 ``` $ ./ext_skel --extname=hello ``` 執行該命令之后它會提示你應當用什么命令來編譯模塊,可惜那是將模塊集成到php內部的編譯方法。如果要編譯成可動態加載的 `php_hello.so`,方法要更為簡單。 進入hello目錄 ``` $ cd hello ``` 首先編輯 `config.m4`文件,去掉第16行和第18行的注釋(注釋符號為 dnl 。) ``` 16: PHP_ARG_ENABLE(hello, whether to enable hello support, 17: dnl Make sure that the comment is aligned: 18: [ --enable-hello Enable hello support]) ``` 然后執行 phpize 程序,生成configure腳本: ``` $ phpize ``` 然后打開 `php_hello.h`,在 PHP_FUNCTION(confirm_hello_compiled); 之下加入函數聲明: ``` PHP_FUNCTION(confirm_hello_compiled); /* For testing, remove later. */ PHP_FUNCTION(hello_add); ``` 打開 hello.c,在 PHP_FE(confirm_hello_compiled, NULL) 下方加入以下內容。 ``` zend_function_entry hello_functions[] = { PHP_FE(confirm_hello_compiled, NULL) /* For testing, remove later. */ PHP_FE(hello_add, NULL) /* For testing, remove later. */ {NULL, NULL, NULL} /* Must be the last line in hello_functions[] */ }; ``` 然后在 hello.c 的最末尾書寫hello_add函數的內容: ``` PHP_FUNCTION(hello_add) { long int a, b; long int result; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &a, &b) == FAILURE) { return; } result = hello_add(a, b); RETURN_LONG(result); } ``` #### hello.c文件的主要開發 ``` ZEND_BEGIN_ARG_INFO(arg_say_goodbye, 0) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() const zend_function_entry fetion_echo_functions[] = { PHP_FE(say_goodbye, arg_say_goodbye) {NULL, NULL, NULL} }; ZEND_BEGIN_ARG_INFO(name, 0|1) ``` 以`ZEND_BEGIN_ARG_INFO`宏定義開始,以`ZEND_END_ARG_INFO()`結束,這兩個宏定義解釋如下: ``` ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference): 開始參數塊定義,pass_rest_by_reference為1時,強制所有參數為引用類型 ZEND_END_ARG_INFO() : 結束參數塊定義 而每一個參數的定義可以是下列宏定義中的一個: ZEND_ARG_INFO 聲明普通參數 ZEND_ARG_OBJ_INFO 聲明對象類型的參數 ZEND_ARG_ARRAY_INFO 聲明數組類型的參數 ZEND_ARG_PASS_INFO(pass_by_ref) pass_by_ref為1時,強制設置后續的參數為引用類型 ``` 舉個例子,如果我們要定義一個函數user_login(username, password),則參數的聲明如下: ``` ZEND_BEGIN_ARG_INFO(arg_user_login, 0) ZEND_ARG_INFO(0, username) ZEND_ARG_INFO(0, password) ZEND_END_ARG_INFO() ``` 根據Zend API宏定義,上面的參數聲明展開后,大致如下: ``` static const zend_arg_info arg_user_login[] = { \ { NULL, 0, NULL, 0, 0, 0, 0, 0, 0 }, { "username", sizeof(“username“)-1, NULL, 0, 0, 0, 0, 0, 0 }, { "password", sizeof(“password“)-1, NULL, 0, 0, 0, 0, 0, 0 }, } ``` 可以看到,其實我們定義參數信息展開后就是一個`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; zend_bool pass_by_reference; zend_bool return_reference; int required_num_args; } zend_arg_info; ``` 下面對各個字段做一解釋: ``` name 參數名稱 name_len 參數名稱字符串長度 class_name 當參數類型為類時,指定類名稱 class_name_len 類名稱字符串長度 array_type_hint 標識參數類型是否為數組 allow_null 是否允許設置為空 pass_by_reference 是否設置為引用,即使用&操作符 return_reference 標識函數將重寫return_value_ptr,后面介紹函數返回值時再做介紹 required_num_args 設置函數被調用時,傳遞參數至少為前N個,當設置為-1時,必須傳遞所有參數 ``` #### 保存退出,編譯并安裝: ``` $ ./configure $ make LDFLAGS=-lhello(重點) $ su # cp modules/hello.so /usr/lib/php/modules ./configure --with-php-config=/www/server/php/71/bin/php-config && make clean && make LDFLAGS=-lhello && make LDFLAGS=-lunionAPI && sudo make install ``` 然后在 `/var/www/html` 下建立一個 hello.php 文件,內容如下: 使用dl會報錯(dl("hello.so");) ``` <?php echo hello_add(3, 4); ?> ``` ### 數據類型表格 ``` 類型指定符 對應的C類型 描述 l long 符號整數 d double 浮點數 s char *, int 二進制字符串,長度 b zend_bool 邏輯型(1或0) r zval * 資源(文件指針,數據庫連接等) a zval * 聯合數組 o zval * 任何類型的對象 O zval * 指定類型的對象。需要提供目標對象的類類型 z zval * 無任何操作的zval ``` [參考鏈接](https://www.cnblogs.com/doseoer/p/4367565.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>

                              哎呀哎呀视频在线观看