<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、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 5.4 編寫函數 前面我們已經生成好了一份擴展框架,但它是沒有什么實際作用的。一個擴展的作用可大了去了,既可以操作PHP中的變量、常量,還可以定義函數、類、方法、資源等。先讓我們從函數說起吧! ### ZEND_FUNCTION()宏函數 ZEND_FUNCTION()宏函數也可以寫成PHP_FUNCTION(),但ZEND_FUNCTION()更前衛、標準一些,但兩者是完全相同的。 ````c #define PHP_FUNCTION ZEND_FUNCTION #define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name)) #define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS) #define ZEND_FN(name) zif_##name ```` 其中,zif是zend internal function的意思,zif_前綴是可供PHP語言調用的函數在C語言中的函數名稱前綴。 ````c ZEND_FUNCTION(walu_hello) { php_printf("Hello World!\n"); } ```` 上面定義了一個函數,在C語言中展開后應該是這樣的: ````c void zif_walu_hello(INTERNAL_FUNCTION_PARAMETERS) { php_printf("Hello World!\n"); } ```` 上面的展開式僅供參考,絕不推薦在編程時使用,我們應該采用宏的形式,來提高程序的兼容性與可讀性。 上面的代碼定義了一個可供用戶在PHP語言中調用的函數實現,但現在用戶還不能在程序中調用,因為這個函數還沒有與用戶端建立聯系,也就是說雖然我們在C中完成了它的實現,但用戶端PHP語言還根本不知道它的存在呢。 現在我們回頭看一下5.1節中我們為擴展定義的zend_module_entry walu_module_entry(它是聯系C擴展與PHP語言的重要紐帶)中的“NULL, /* Functions */”,當時我們為它賦予了NULL,是因為還沒有函數,現在我們已經為它編寫了函數了,便可以給它賦予一個新值了,這個值需要是zend_function_entry[]類型的,首先讓我們來構造這個重要數據。 ````c static zend_function_entry walu_functions[] = { ZEND_FE(walu_hello, NULL) { NULL, NULL, NULL } }; /* 下面是ZEND_FE的定義 #define ZEND_FE(name, arg_info) ZEND_FENTRY(name, ZEND_FN(name), arg_info, 0) #define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags }, ZEND_FE(walu_hello, NULL)展開后便是: {"walu_hello",zif_walu_hello,NULL, (zend_uint) (sizeof(NULL)/sizeof(struct _zend_arg_info)-1), 0 }, */ ```` 其中最后的{NULL,NULL,NULL}是固定不變的。ZEND_FE()宏函數是對我們walu_hello函數的一個聲明,如果我們有多個函數,可以直接以類似的形式添加到{NULL,NULL,NULL}之前,注意每個之間不需要加逗號。 其中的arg_info我們現在先賦予NULL就行了,我們將在第7章討論這個參數。確保一切無誤后,我們替換掉zend_module_entry里的原有成員,現在應該是這樣的: ````c ZEND_FUNCTION(walu_hello) { php_printf("Hello World!\n"); } static zend_function_entry walu_functions[] = { ZEND_FE(walu_hello, NULL) { NULL, NULL, NULL } }; zend_module_entry walu_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "walu", //這個地方是擴展名稱,往往我們會在這個地方使用一個宏。 walu_functions, /* Functions */ NULL, /* MINIT */ NULL, /* MSHUTDOWN */ NULL, /* RINIT */ NULL, /* RSHUTDOWN */ NULL, /* MINFO */ #if ZEND_MODULE_API_NO >= 20010901 "2.1", //這個地方是我們擴展的版本 #endif STANDARD_MODULE_PROPERTIES }; ```` 現在configure、make、make test,復制到extension dir。用下面這個命令來測試下,應該會輸出hello world了,如果沒有輸出,說明你哪個地方做錯了,查不出來的話可以給我發mail,看看是不是特例:-) ````c $ php -r 'walu_hello();' ```` ## Zend Internal Functions zif_前綴在前面我們已經說過了,代表著"Zend Internal Function",主要用來避免命名沖突,比如PHP語言中有個strlen()函數,而C語言中也有strlen()函數,所以PHP中的strlen在C中的實現不能是strlen,而應改是一個不同的名字。 但是有些時候盡管我們加了zif_前綴,還會出現一些沖突問題。比如函數名稱本身是一個宏名稱從而被編譯器替換掉了。在這種情況下,我們需要手動來為我們擴展中的函數命名,這一步操作通過ZEND_NAMED_FUNCTION(diy_walu_hello)來代替ZEND_FUNCTION(hello_hello)。前者由我們指定名稱,后者自己加上前綴。 如果我們在定義函數時使用了ZEND_NAMED_FUNCTION(),那么在walu_functions[]里,我們需要用ZEND_NAMED_FE()宏來代替ZEND_FE()宏。即:ZEND_NAMED_FE(walu_hello,diy_walu_hello,NULL) 上面的技術在ext/standard/file.c用到了,我們可以看fopen()函數的定義:PHP_NAMED_FUNCTION(php_if_fopen)。但是用戶端不會感覺到任何變化,還是用fopen函數來使用,因為zend_function_entry中每一項的第一個值代表這此函數在PHP語言中的名稱。Internally, however, the function is protected from being mangled by preprocessor macros and over-helpful compilers.(原作者說的這個理由我也沒看明白,請知者指點) ## Function Aliases 去PHP手冊里查一下pos()函數,會得到這么一條信息:"This function is an alias of: current()";也就是說,它只是current的一個軟鏈接而已,類似linux中的ln -s命令,理解成win下的快捷方式也成。運行pos函數,其實就是在運行current函數,轉接了一下而已。這往往是因為版本升級引起的,新版本中的程序提供了某個功能的新的實現,先為原來的函數改個名,但還需要保留原來的函數名,所以這就用到了alias。這個功能可以在內核中通過ZEND_NAMED_FE宏來實現。 ````c static zend_function_entry walu_functions[] = { ZEND_FE(walu_hello, NULL) ZEND_NAMED_FE(walu_hi, ZEND_FN(walu_hello), NULL) { NULL, NULL, NULL } }; /* ZEND_NAMED_FE也可以寫成PHP_NAMED_FE,但推薦用前者 #define ZEND_NAMED_FE(zend_name, name, arg_info) ZEND_FENTRY(zend_name, name, arg_info, 0) */ ```` 通過ZEND_NAMED_FE的展開式我們了解到,它只是把PHP語言中的兩個函數的名字對應到同一個C語言函數而已。 其實還有另外一種寫法: ````c static zend_function_entry walu_functions[] = { ZEND_FE(walu_hello, NULL) ZEND_FALIAS(walu_hi,walu_hello, NULL) { NULL, NULL, NULL } }; /* #define ZEND_FALIAS(name, alias, arg_info) ZEND_FENTRY(name, ZEND_FN(alias), arg_info, 0) */ ```` 展開式是一樣的,真不清楚官方鼓搗這么多同樣的宏干啥。 ````php <?php walu_hi(); walu_hello(); ```` ## links * 5.3 [靜態編譯](<5.3.md>) * 5.5 [第五章小結](<5.5.md>)
                  <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>

                              哎呀哎呀视频在线观看