《PHP編程:PHP擴(kuò)展開發(fā)入門教程》要點(diǎn):
本文介紹了PHP編程:PHP擴(kuò)展開發(fā)入門教程,希望對您有用。如果有疑問,可以聯(lián)系我們。
PHP實(shí)戰(zhàn)PHP擴(kuò)大開發(fā)
PHP實(shí)戰(zhàn)我準(zhǔn)備在此系列博文中總結(jié)我有關(guān)PHP擴(kuò)展開發(fā)的學(xué)習(xí)和感悟,力圖簡單清晰地描述在Linux系統(tǒng)下開發(fā)一個PHP擴(kuò)展應(yīng)該具備的最基本知識.水平較低,不免有錯誤,望指出.
PHP實(shí)戰(zhàn)準(zhǔn)備事情
PHP實(shí)戰(zhàn)首先要獲取一份PHP源碼(可以從Github上簽出,或者到官網(wǎng)上下載最新的穩(wěn)定版),然后編譯之.為了加快編譯速度,我們推薦禁用所有額外的擴(kuò)展(使用--disable-all選項),但最好打開debug(使用--enable-debug選項)和線程平安(使用--enable-maintainer-zts),但要在發(fā)布擴(kuò)展的時候關(guān)閉debug,視情況選擇是否需要打開線程平安:
PHP實(shí)戰(zhàn)編譯后的PHP的可執(zhí)行程序在源碼的sapi目錄下,對應(yīng)不同的宿主環(huán)境有不同的子目錄,我們以后都主要使用cli(command line interface)環(huán)境,可以建一個別名方便引用:
PHP實(shí)戰(zhàn)有一些敕令行選項是很有用的:
PHP實(shí)戰(zhàn)擴(kuò)展骨架
PHP實(shí)戰(zhàn)PHP的所有官方擴(kuò)展都在源碼的ext目錄下,我們本身寫的擴(kuò)展也可以放在該目錄下.注意,該目錄下有個名為ext_skel的shell腳本,它是用來生成PHP擴(kuò)展骨架的,使用該腳本,可以幫我們快速創(chuàng)建PHP擴(kuò)展:
PHP實(shí)戰(zhàn)接下來讓我們完成我們的擴(kuò)展.進(jìn)入myext目錄,編輯config.m4配置文件,找到PHP_ARG_ENABLE宏函數(shù),去掉前面的dnl注釋(共三行).退回到源碼根目錄,重新執(zhí)行buildconf、configure和make命令:
PHP實(shí)戰(zhàn)注意,我們用./configure --help | grep myext打印了我們擴(kuò)展的加載情況,如果看不到下面的輸出,則闡明我們的擴(kuò)展沒有配置成功,回頭檢查下config.m4文件.
PHP實(shí)戰(zhàn)這次編譯應(yīng)該非???因為大部分代碼都已經(jīng)編譯過了.PHP還有另外一種編譯擴(kuò)展的辦法(使用動態(tài)連接的方式,將擴(kuò)展編譯為.so的文件),不過我們推薦在開發(fā)擴(kuò)展的時候使用靜態(tài)編譯,因為這樣省去了在配置文件中加載擴(kuò)展的步驟.
PHP實(shí)戰(zhàn)一切順利的話,我們的第一個擴(kuò)大就已經(jīng)可以執(zhí)行了:
PHP實(shí)戰(zhàn)手動創(chuàng)建擴(kuò)展
PHP實(shí)戰(zhàn)大部分教程都是以ext_skel擴(kuò)展骨架為原型講述擴(kuò)展開發(fā)的,這種做法當(dāng)然很便利快捷.但是我個人更喜歡純手工開發(fā)擴(kuò)展的方式,因為這樣更容易理解其中的每一個細(xì)節(jié).
PHP實(shí)戰(zhàn)手動創(chuàng)建擴(kuò)展,先進(jìn)入ext目錄,創(chuàng)建我們的擴(kuò)展目錄myext2.有幾個文件是必需的:config.m4,myext2.c和php_myext2.h.
PHP實(shí)戰(zhàn)首先,我們來編寫設(shè)置裝備擺設(shè)文件config.m4:
PHP實(shí)戰(zhàn)if test "PHP_MYEXT2" != "no"; then
?? PHP_NEW_EXTENSION(myext2, myext2.c, $ext_shared)
fi
PHP實(shí)戰(zhàn)PHP_ARG_ENABLE是PHP為autoconf定義的宏函數(shù),myext2是它的第一個參數(shù),指出了擴(kuò)展的名字;后面兩個參數(shù)只是在make和configure執(zhí)行時用來顯示的,所以我們可以隨便寫.[ ]在autoconf語法中的作用類似于雙引號,用來包裹字符串(注意第二個參數(shù)中包括了空格,但是可以不用方括號起來).還有第四個參數(shù)用來指明擴(kuò)展默認(rèn)是開啟還是關(guān)閉(yes或no),默認(rèn)是no.
PHP實(shí)戰(zhàn)下面三行其實(shí)便是shell語法,判斷我們是否開啟了PHP_MYEXT2擴(kuò)展模塊.如果開啟了該擴(kuò)展模塊(--enable-myext2),則$PHP_MYEXT2變量的值不為no,因此執(zhí)行PHP_NEW_EXTENSION宏.這個宏函數(shù)也是PHP為autoconf定義的擴(kuò)展語法,第一個參數(shù)同樣是擴(kuò)展名稱;第二個參數(shù)是擴(kuò)展要編譯的C文件,如果有多個,依次寫下去就可以了(空格分隔);第三個參數(shù)固定是$ext_shared.
PHP實(shí)戰(zhàn)接下來編寫php_myext2.h頭文件,該文件的定名是PHP擴(kuò)展的規(guī)范 ― php_擴(kuò)展名.h:
PHP實(shí)戰(zhàn)extern zend_module_entry myext2_module_entry;
#define phpext_myext2_ptr &myext2_module_entry
PHP實(shí)戰(zhàn)#define PHP_MYEXT2_VERSION "0.1.0"
PHP實(shí)戰(zhàn)/* prototypes */
PHP_FUNCTION(hello);
PHP實(shí)戰(zhàn)#endif? /* PHP_MYEXT2_H */
PHP實(shí)戰(zhàn)這里主要的代碼是定義了名為phpext_myext2_ptr的宏,PHP底層通過該宏來引用我們的擴(kuò)展.可以看出,該宏的命名同樣是有規(guī)范的 ― phpext_擴(kuò)展名_ptr.而myext2_module_entry是我們稍后要在.c文件里定義的布局體,它的命名也是規(guī)范的 ― 擴(kuò)展名_module_entry.
PHP實(shí)戰(zhàn)此外我們還界說了一個標(biāo)識我們擴(kuò)展版本號的宏和一個函數(shù)原型(通過PHP_FUNCTION宏,PHP_FUNCTION宏函數(shù)的參數(shù)是外部可使用的函數(shù)名),稍后我們會來實(shí)現(xiàn)這個函數(shù).
PHP實(shí)戰(zhàn)末了來看下myext2.c文件的實(shí)現(xiàn):
PHP實(shí)戰(zhàn)/* {{{ myext2_functions[]
?*
?* Every user visible function must have an entry in myext2_functions[].
?*/
static const zend_function_entry myext2_functions[] = {
??? PHP_FE(hello,?????? NULL)
??? PHP_FE_END
};
/* }}} */
PHP實(shí)戰(zhàn)/* {{{ myext2_module_entry
?*/
zend_module_entry myext2_module_entry = {
??? STANDARD_MODULE_HEADER,
??? "myext2",?????????????? /* module name */
??? myext2_functions,?????? /* module functions */
??? NULL,?????????????????? /* module initialize */
??? NULL,?????????????????? /* module shutdown */
??? NULL,?????????????????? /* request initialize */
??? NULL,?????????????????? /* request shutdown */
??? NULL,?????????????????? /* phpinfo */
??? PHP_MYEXT2_VERSION,???? /* module version */
??? STANDARD_MODULE_PROPERTIES
};
/* }}} */
PHP實(shí)戰(zhàn)#ifdef COMPILE_DL_MYEXT2
ZEND_GET_MODULE(myext2)
#endif
PHP實(shí)戰(zhàn)/* {{{ proto void hello()
?? Print "hello world!" */
PHP_FUNCTION(hello)
{
??? php_printf("hello world!\n");
}
/* }}} */
PHP實(shí)戰(zhàn)對比下擴(kuò)展骨架創(chuàng)立的.c文件就會發(fā)現(xiàn),我們的.c文件非常的簡單,其實(shí)這些對一個最基本的擴(kuò)展來說就已經(jīng)足夠了.
PHP實(shí)戰(zhàn)上面的代碼是簡單而清晰的,大部門注釋已經(jīng)很具說明性了.我們再簡要概括下:
PHP實(shí)戰(zhàn)1.開頭包含我們要用到的頭文件.php.h是必須的,它已經(jīng)幫我們包含了我們會用到的絕大多數(shù)的標(biāo)準(zhǔn)庫文件,比如stdio.h,stdlib.h等等.
2.myext2_functions定義了由我們要暴露出去的函數(shù)構(gòu)成的結(jié)構(gòu)體數(shù)組,每一個元素通過PHP_FE宏來指定.PHP_FE宏有兩個參數(shù),第一個是外部可使用的函數(shù)名,第二個是參數(shù)信息(這里我們簡單使用了NULL),最后一個元素必須是PHP_FE_END.注意它的注釋,再次強(qiáng)調(diào),每一個要暴露給外部使用的函數(shù),都必須在該結(jié)構(gòu)體數(shù)組中有定義.
3.myext2_module_entry定義了我們的模塊信息,它是一個結(jié)構(gòu)體,大部分屬性都已經(jīng)通過注釋給出了說明.注意中間的五個函數(shù)指針,我們都簡單的置為了NULL,在后續(xù)的博文中會講述它們的用法.
4.ZEND_GET_MODULE(myext2)宏函數(shù)是被ifdef宏包含的,所以說它是否調(diào)用是視情況而定的.至于什么情況下會被調(diào)用,什么情況下不會被調(diào)用,在后續(xù)的博文中會講述.
5.最后幾行代碼我們實(shí)現(xiàn)了hello函數(shù),它很簡單,調(diào)用php_printf輸出hello world!跟一個換行符,php_printf的用法和printf完全一樣.
6.注釋里的 {{{ 和 }}} 是為了方便vim等編輯器折疊而使用的,我們推薦你也這樣來寫注釋.
這里面涉及了一些宏,比如PHP_FE,PHP_FE_END,PHP_FUNCTION等等,完整介紹這些宏要到后續(xù)的博文中才可以,眼下最簡單的方法就是記住這些宏.
PHP實(shí)戰(zhàn)注意到我們每一個文件的命名,變量的命名,空格和縮進(jìn),以及注釋等都是非常規(guī)范的,遵循這些規(guī)范,可以使我們編寫的代碼和PHP本身的代碼更加契合,我們也保舉你使用這樣的規(guī)范來開發(fā)PHP擴(kuò)展.
PHP實(shí)戰(zhàn)最后,編譯運(yùn)行我們的擴(kuò)大:
PHP實(shí)戰(zhàn)$ php-dev -m | grep myext2
myext2
$ php-dev -r 'hello();'
hello world!
維易PHP培訓(xùn)學(xué)院每天發(fā)布《PHP編程:PHP擴(kuò)展開發(fā)入門教程》等實(shí)戰(zhàn)技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培養(yǎng)人才。
轉(zhuǎn)載請注明本頁網(wǎng)址:
http://www.snjht.com/jiaocheng/12183.html