|
對(duì)大多數(shù)用戶來說,PHP已經(jīng)足夠剽悍了。只有在一些牛叉的企業(yè)級(jí)應(yīng)用中PHP的瓶頸才會(huì)顯現(xiàn)出來,運(yùn)行速度達(dá)不到要求、缺少必要的功能等等。由于語(yǔ)言上的限制,有些功能可能壓根兒沒法用PHP實(shí)現(xiàn)(比如精確到納秒級(jí)別的計(jì)時(shí));維護(hù)一個(gè)每個(gè)腳本都需要使用的一個(gè)超大函數(shù)庫(kù)也是一件令人頭疼的事情(這句翻譯的不太好,原文:inconveniences that arise when having to carry around a huge library of default code appended to every single script),所以我們必須要找到一種方法來克服這些障礙。一旦我們的應(yīng)用有了這樣的需求,是時(shí)候看看PHP內(nèi)核源碼啦~看看C語(yǔ)言是如何讓PHP跑起來的。 擴(kuò)展PHP,說得容易做得難。 而今,PHP已經(jīng)是一個(gè)功能完善、源碼達(dá)數(shù)兆的龐然大物了。想要對(duì)這樣一個(gè)系統(tǒng)加點(diǎn)兒料,咱們得弄明白一些很基本的東西。我們采用邊學(xué)邊做的方法進(jìn)行學(xué)習(xí),也許這并不是最科學(xué)、最專業(yè)的方式,但是我確信這種方式是最有效果的,同時(shí)你會(huì)得到很多樂趣。我們接下來會(huì)看下最最簡(jiǎn)單的擴(kuò)展是如何跑起來的,之后我們來看看Zend所提供的一些高級(jí)功能。當(dāng)然我們也可以先對(duì)Zend的功能、設(shè)計(jì)、技巧分別進(jìn)行學(xué)習(xí)、在動(dòng)手實(shí)踐之前學(xué)習(xí)各種理論,不用做任何hack。但是這樣學(xué)院派的“好”方法是非常令人不爽的,既費(fèi)時(shí)又費(fèi)力,所以我們還是邊學(xué)邊做吧! 注意盡管這章我們要盡可能理解PHP內(nèi)部各個(gè)部分的工作原理,我們也不可能覆蓋到擴(kuò)展PHP的方方面面。師傅領(lǐng)進(jìn)門,學(xué)藝在個(gè)人。只有勤學(xué)苦“練”你才能完全了解它內(nèi)部的各種機(jī)制,所以我們鼓勵(lì)你多和源碼打交道哦~親~ Zend是神馬?PHP又是神馬? Zend其實(shí)是指PHP語(yǔ)言的引擎,PHP的核心。PHP是指包裹這層核心的一個(gè)完整系統(tǒng)。乍一聽這有點(diǎn)兒丈二和尚摸不著頭腦,但是這并不復(fù)雜(往下看)。一個(gè)網(wǎng)絡(luò)腳本解釋器由如下三部分組成。 1、解釋器解析輸入代碼,翻譯并將其執(zhí)行。 2、函數(shù)庫(kù)實(shí)現(xiàn)語(yǔ)言的各個(gè)功能。 3、和服務(wù)器打交道的接口。 Zend完整地實(shí)現(xiàn)了第一部分,部分實(shí)現(xiàn)了第二和第三部分。這三部分共同組成了完整的PHP。Zend是語(yǔ)言核心,使用一些預(yù)定義函數(shù)構(gòu)建了PHP的地基。PHP的各種模塊才是使得它綻放萬(wàn)丈光芒的原因。 下面我們來看看PHP在哪些地方可以擴(kuò)展,又是怎么做到的。 [擴(kuò)展可行性分析]: 如上圖所示,PHP可以在三個(gè)地方進(jìn)行擴(kuò)展:外部模塊、內(nèi)部模塊、Zend引擎。接下來我們分別對(duì)這三種方法進(jìn)行學(xué)習(xí)。 [外部模塊]: 外部模塊可以在腳本運(yùn)行時(shí)由dl()函數(shù)進(jìn)行加載。dl()函數(shù)將一個(gè)動(dòng)態(tài)鏈接庫(kù)從磁盤加載到內(nèi)存,使得綁定在這個(gè)庫(kù)上的函數(shù)得以被腳本調(diào)用。當(dāng)腳本運(yùn)行完畢時(shí),外部模塊被請(qǐng)出內(nèi)存,釋放其所占用的空間。這種方法有利有弊 利 外部模塊不需要重新編譯PHP PHP在大小不發(fā)生變化的情況下擴(kuò)展了新的功能。 弊 每次執(zhí)行腳本都需要加載,要知道磁盤IO是很慢地。 你的磁盤會(huì)被額外的文件占滿。。。 注:每個(gè)需要使用外部模塊的腳本都必須調(diào)用dl()函數(shù)指定所需模塊,要么就必須在php.ini中注明需要加載的動(dòng)態(tài)鏈接庫(kù)(windows是.dll,linux和mac是.so)。 總結(jié)起來,外部模塊適用于PHP的第三方產(chǎn)品,不常用的小擴(kuò)展或者專為測(cè)試時(shí)使用。如果你要快速開發(fā)擴(kuò)展,外部模塊應(yīng)該是你的首選。然而對(duì)于那些常用的、大型應(yīng)用以及復(fù)雜代碼來說,就是弊大于利了。 [內(nèi)部模塊]: 內(nèi)部模塊是那些和PHP一起進(jìn)行編譯,每次執(zhí)行腳本時(shí)都會(huì)使用、加載的模塊。它們所提供的函數(shù)每個(gè)腳本都可以直接調(diào)用。和外部模塊一樣,內(nèi)部莫卡也是有利弊的。 利: 不用指定加載文件,功能都是內(nèi)置的。 不會(huì)占用額外的空間,一切都已經(jīng)在PHP二進(jìn)制文件中了。 弊: 任何改動(dòng)都需要重新編譯PHP PHP二進(jìn)制文件會(huì)占用更多內(nèi)存。 內(nèi)部模塊適用于那些相對(duì)不變的庫(kù)、較高的性能要求或是項(xiàng)目中很多腳本需要調(diào)用且頻繁使用的情況。重新編譯PHP的不快很快就隨著使用方便和飛快的速度所帶來的享受而煙消云散。但是內(nèi)部模塊不適合應(yīng)用在那些需要快速開發(fā)的小擴(kuò)展上。 [Zend引擎] 當(dāng)然,擴(kuò)展也可以直接實(shí)現(xiàn)在Zend引擎內(nèi)部。這種方法常用于修改PHP語(yǔ)言,使得它滿足特殊需要??偟膩碚f,我們應(yīng)該盡量避免直接修改Zend引擎。要知道你在引擎里的任何改動(dòng)都會(huì)導(dǎo)致你所使用的PHP語(yǔ)言無(wú)法兼容新版本。。。如果進(jìn)行升級(jí),它才不會(huì)檢查你現(xiàn)在跑著的PHP有啥不同呢,它會(huì)直接覆蓋你的代碼,編譯然后安裝!因此這種方法真是不咋地,我們也不會(huì)在本書里講到這種方法。(當(dāng)然學(xué)習(xí)完這一系列內(nèi)容,你應(yīng)該有這樣的本事,對(duì)PHP源碼進(jìn)行改動(dòng)) [源碼結(jié)構(gòu)] 在我們學(xué)習(xí)任何源碼的時(shí)候,你都必須先對(duì)源碼樹有所了解,以便你能快速對(duì)PHP的文件進(jìn)行劃分。這是編寫擴(kuò)展所需的最基本能力。 php-src PHP中主要的.c文件和.h頭文件;你可以在這里看到PHP全部API、宏等內(nèi)容的定義 php-src/ext 用于存放動(dòng)態(tài)鏈接庫(kù)(模塊)和內(nèi)部模塊;默認(rèn)情況下,這個(gè)文件夾里的內(nèi)容是PHP官方模塊,已經(jīng)內(nèi)置到PHP源碼中。并且從PHP4.0開始,你已經(jīng)可以采用動(dòng)態(tài)加載的方法編譯安裝它們。(通過--enable-shared) php-src/main 用于存放PHP各種宏定義 php-src/pear PHP擴(kuò)展和應(yīng)用庫(kù)(PEAR),該文件夾存放著PEAR核心文件 php-src/sapi 各種和服務(wù)器交互的接口 TSRM Zend和PHP的安全線程資源管理器 ZendEngine2 用于存放Zend引擎;這里你可以看到全部的Zend API定義、宏定義等等 我們可不是在學(xué)習(xí)PHP源碼,所以就不在此展開了。但是你應(yīng)該看看以下幾個(gè)文件: php-src/main/php.h,該文件定義了大多數(shù)PHP宏和API php-src/Zend/Zend.h,該文件定義了大多數(shù)Zend引擎的宏 php-src/Zend/zend_API.h,該文件定義了Zend引擎的API 同時(shí)你也應(yīng)該看看這些文件,包括Zend executor,PHP初始化文件等等??催^這些文件之后試試找出各個(gè)文件和模塊之間的依賴關(guān)系。它們之間有什么關(guān)系,如何相互使用的。在這個(gè)過程中你可以學(xué)到PHP官方的編碼規(guī)范。為了擴(kuò)展PHP,你應(yīng)該盡快熟悉這種規(guī)范。 [擴(kuò)展規(guī)范] Zend有著各種命名規(guī)范;為了避免和Zend標(biāo)準(zhǔn)相沖突,你應(yīng)該遵守如下幾條規(guī)范。 [宏定義] 對(duì)于每項(xiàng)重要的工作(比如分配內(nèi)存、動(dòng)態(tài)加載鏈接庫(kù)啥的),使用Zend自己預(yù)定義的宏是相當(dāng)方便的。下面的章節(jié)我們來看看一些非常基本的函數(shù)、結(jié)構(gòu)體和宏。記住你可以在zend.h和zend_API.h中找到這些定義。我們強(qiáng)烈建議您看過本章后仔細(xì)閱讀這兩個(gè)文件。(當(dāng)然你可以現(xiàn)在就讀,盡管有些內(nèi)容你可能并不太明白) [內(nèi)存管理] 資源管理從來都是非常重要的環(huán)節(jié),特別是在服務(wù)器端軟件。最重要的資源之一是內(nèi)存,所以需要額外注意那些用于管理內(nèi)存的程序。在Zend中,內(nèi)存管理被單獨(dú)抽象出來,你應(yīng)該特別注意這一點(diǎn),因?yàn)閆end可以完全控制內(nèi)存分配。Zend可以判斷一塊內(nèi)存是否正被使用,自動(dòng)釋放不再使用的塊以及空引用指向的塊,從而有可能造成內(nèi)存泄露。你可以使用如下函數(shù)管理內(nèi)存。 emalloc() 代替 malloc(). efree() 代替 free(). estrdup() 代替 strdup(). estrndup() 代替 strndup(). 比 estrdup() 快并且更安全,在已知字符串字節(jié)長(zhǎng)度的情況下,你應(yīng)該用這個(gè)函數(shù)去復(fù)制 ecalloc() 代替 calloc(). erealloc() 代替 realloc(). emalloc(), estrdup(), estrndup(), ecalloc(), 和 erealloc() 用于分配內(nèi)存。 efree() 釋放這些被分配的內(nèi)存。由E開頭的函數(shù)分配的內(nèi)存,會(huì)在當(dāng)前進(jìn)程執(zhí)行腳本結(jié)束后自動(dòng)釋放。 注意:你也可以用malloc和free去分配釋放內(nèi)存,但是這些內(nèi)存是不會(huì)隨腳本結(jié)束而釋放的,所以有可能會(huì)造成內(nèi)存泄露。 Zend還提供了一個(gè)線程安全的資源管理器,以便更好地支持多線程服務(wù)器。它要求你為全局變量分配好本地內(nèi)存,供當(dāng)前線程使用。因?yàn)楸疚淖珜憰r(shí)線程安全資源管理器還木有寫好,所以我們?cè)诖司筒蛔鲇懻摿?。?!?/p> [文件夾和文件函數(shù)] 你可以在編寫與文件或者文件夾相關(guān)的程序中使用如下函數(shù)。它們用起來其實(shí)和C語(yǔ)言中的親戚沒啥區(qū)別,只是額外在線程級(jí)別提供了虛擬路徑。 Zend 函數(shù) C語(yǔ)言函數(shù) V_GETCWD() getcwd() V_FOPEN() fopen() V_OPEN() open() V_CHDIR() chdir() V_GETWD() getwd() V_CHDIR_FILE() 以文件路徑為參數(shù),切換當(dāng)前工作路徑到那個(gè)路徑。(V_CHDIR_FILE("/") = cd /) V_STAT() stat() V_LSTAT() lstat() [字符串操作] 字符串操作起來和其它值,如整數(shù)、布爾變量有些不同,你不用分配內(nèi)存去存儲(chǔ)字符串。如果你想在函數(shù)中返回一個(gè)字符串值,可以在符號(hào)表里插入一個(gè)字符串變量,或者使用其它相似的辦法,總之你得保證分配給字符串的內(nèi)存在之前已經(jīng)分配過了,記得使用e開頭的函數(shù)哦~親~(可能現(xiàn)在你看不懂介是啥意思,沒事兒,有個(gè)印象就成,一會(huì)兒會(huì)解釋的) [復(fù)雜類型] 復(fù)雜數(shù)據(jù)類型如數(shù)組、對(duì)象需要特殊對(duì)待。Zend對(duì)此提供了一個(gè)簡(jiǎn)單API——將它們存儲(chǔ)于哈西表中。 說說數(shù)組和對(duì)象的這個(gè)哈西表 注:為了降低復(fù)雜性,我們先使用一些簡(jiǎn)單的數(shù)據(jù)類型,如整數(shù)。稍后我們?cè)倏锤呒?jí)的數(shù)據(jù)類型如何使用。 [PHP自建系統(tǒng)] PHP4提供了一個(gè)非常靈活的自建系統(tǒng)。所有的模塊都被放置于ext文佳夾中的子文件夾中(一般文件夾名就是模塊名)。除了模塊源碼之外,每個(gè)模塊都含有一個(gè)叫做config.m4的文件,用于配置模塊。 所有的stub文件(萬(wàn)分抱歉我實(shí)在不知道這個(gè)詞是啥意思,中文有對(duì)應(yīng)翻譯嗎?)由ext文件夾中的一個(gè)叫ext_skel的腳本都是自動(dòng)生成的,它將你所想創(chuàng)建的模塊的名稱作為參數(shù),創(chuàng)建出同名文件夾,并將stub文件放置于文件夾中。 過程是醬紫的: :~/cvs/php4/ext:> ./ext_skel --extname=my_module Creating directory my_module Creating basic files: config.m4 .cvsignore my_module.c php_my_module.h CREDITS EXPERIMENTAL tests/001.phpt my_module.php [done]. 為了使用新擴(kuò)展,你需要執(zhí)行如下命令 1. $ cd .. 2. $ vi ext/my_module/config.m4 3. $ ./buildconf 4. $ ./configure --[with|enable]-my_module 5. $ make 6. $ ./php -f ext/my_module/my_module.php 7. $ vi ext/my_module/my_module.c 8. $ make 反復(fù)執(zhí)行步驟3-6直到你對(duì)/ext/my_module/config.m4文件滿意為止,步驟6使得你的擴(kuò)展直接被編譯進(jìn)PHP。最后你可以通過反復(fù)修改并執(zhí)行最后兩步達(dá)到最佳擴(kuò)展效果 上述命令創(chuàng)建了之前提到的文件。要想自動(dòng)配置新擴(kuò)展,你需要執(zhí)行buildconf,通過搜索ext文件夾下的全部config.m4文件,重新生成配置腳本。 以下是一個(gè)默認(rèn)的config.m4文件,有點(diǎn)兒小復(fù)雜: 例1:默認(rèn)的config.m4文件 dnl $Id: build.xml 297078 2010-03-29 16:25:51Z degeberg $ dnl config.m4 for extension my_module dnl Comments in this file start with the string 'dnl'. dnl Remove where necessary. This file will not work dnl without editing. dnl If your extension references something external, use with: dnl PHP_ARG_WITH(my_module, for my_module support, dnl Make sure that the comment is aligned: dnl [ --with-my_module Include my_module support]) dnl Otherwise use enable: dnl PHP_ARG_ENABLE(my_module, whether to enable my_module support, dnl Make sure that the comment is aligned: dnl [ --enable-my_module Enable my_module support]) if test "$PHP_MY_MODULE" != "no"; then dnl Write more examples of tests here... dnl # --with-my_module -> check with-path dnl SEARCH_PATH="/usr/local /usr" # you might want to change this dnl SEARCH_FOR="/include/my_module.h" # you most likely want to change this dnl if test -r $PHP_MY_MODULE/; then # path given as parameter dnl MY_MODULE_DIR=$PHP_MY_MODULE dnl else # search default path list dnl AC_MSG_CHECKING([for my_module files in default path]) dnl for i in $SEARCH_PATH ; do dnl if test -r $i/$SEARCH_FOR; then dnl MY_module_DIR=$i dnl AC_MSG_RESULT(found in $i) dnl fi dnl done dnl fi dnl dnl if test -z "$MY_module_DIR"; then dnl AC_MSG_RESULT([not found]) dnl AC_MSG_ERROR([Please reinstall the my_module distribution]) dnl fi dnl # --with-my_module -> add include path dnl PHP_ADD_INCLUDE($MY_MODULE_DIR/include) dnl # --with-my_module -> chech for lib and symbol presence dnl LIBNAME=my_module # you may want to change this dnl LIBSYMBOL=my_module # you most likely want to change this dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, dnl [ dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $MY_MODULE_DIR/lib, MY_MODULE_SHARED_LIBADD) dnl AC_DEFINE(HAVE_MY_MODULELIB,1,[ ]) dnl ],[ dnl AC_MSG_ERROR([wrong my_module lib version or lib not found]) dnl ],[ dnl -L$MY_module_DIR/lib -lm -ldl dnl ]) dnl dnl PHP_SUBST(MY_module_SHARED_LIBADD) PHP_NEW_EXTENSION(my_module, my_module.c, $ext_shared) fi 如果你不熟悉M4文件,扎一看會(huì)有點(diǎn)兒暈,但其實(shí)它還是挺容易理解的。 注意:dnl開頭的行是注釋~ 在配置過程中,config.m4文件主要負(fù)責(zé)生成configure命令的控制選項(xiàng)。也就是說它也要負(fù)責(zé)檢測(cè)需要用到的外部依賴,做些基本的配置工作。 默認(rèn)會(huì)在configure腳本中創(chuàng)建兩個(gè)配置選項(xiàng):--with-my_module 和 --enable-my_module。第一個(gè)是在你需要用到外部文件的時(shí)候使用的(比如 --with-apache 代表了使用Apache目錄中的文件)。第二個(gè)顧名思義,可以用它控制是否讓你的模塊可用。你不能同時(shí)使用這兩個(gè)選項(xiàng),選了--with-my_module你就不能用第二個(gè),反之亦然。 默認(rèn)情況下,ext_skel腳本生成的config.m4文件同時(shí)含有這兩個(gè)指令,并默認(rèn)將你的擴(kuò)展設(shè)置為可用。通過一個(gè)名為PHP_EXTENSION的宏你的擴(kuò)展被默認(rèn)設(shè)為可用。如果你要改變默認(rèn)設(shè)置,將你的模塊直接添加到PHP可執(zhí)行文件中(在配置PHP時(shí)顯示設(shè)置--enable-my_module或者--with-my_module),請(qǐng)將$PHP_MY_MODULE測(cè)試設(shè)置為“是” if test "$PHP_MY_MODULE" == "yes"; then dnl Action.. PHP_EXTENSION(my_module, $ext_shared) fi 如果這樣你必須在每次重新配置編譯PHP的時(shí)候使用 --enable-my_module。 注:務(wù)必記得在改動(dòng)config.m4之后使用buildconf 稍后我們會(huì)學(xué)習(xí)更多M4文件中的宏?,F(xiàn)在我們只用這個(gè)最簡(jiǎn)單的默認(rèn)配置就可以了。 [創(chuàng)建模塊] 我們將從創(chuàng)建最簡(jiǎn)單模塊的開始,它的唯一功能就是接收一個(gè)整形參數(shù)并將其返回??聪略创a。 例2:簡(jiǎn)單模塊 /* include standard header */ #include "php.h" /* declaration of functions to be exported */ ZEND_FUNCTION(first_module); /* compiled function list so Zend knows what's in this module */ zend_function_entry firstmod_functions[] = { ZEND_FE(first_module, NULL) {NULL, NULL, NULL} }; /* compiled module information */ zend_module_entry firstmod_module_entry = { STANDARD_MODULE_HEADER, "First Module", firstmod_functions, NULL, NULL, NULL, NULL, NULL, NO_VERSION_YET, STANDARD_MODULE_PROPERTIES }; /* implement standard "stub" routine to introduce ourselves to Zend */ #if COMPILE_DL_FIRST_MODULE ZEND_GET_MODULE(firstmod) #endif /* implement function that is meant to be made available to PHP */ ZEND_function(first_module) { long parameter; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", ?meter) == FAILURE) { return; } RETURN_LONG(parameter); } 麻雀雖小,五臟俱全!不管你信步信,這已經(jīng)是一個(gè)完整的模塊了。我們稍后將對(duì)其進(jìn)行詳細(xì)的講解,咱們先來看看編譯流程。 注:源碼使用了些PHP 4.1.0之后的API,所以使用PHP 4.0.X的童鞋有可能無(wú)法編譯。 [編譯模塊] 有兩種編譯模塊的方法: 1、使用ext文件夾提供的make機(jī)制,可以動(dòng)態(tài)加載模塊 2、手動(dòng)編譯 我們強(qiáng)烈推薦第一種方法。從PHP4.0開始,這一復(fù)雜的編譯過程成為了標(biāo)準(zhǔn)。不幸的是,它復(fù)雜到你一開始可能無(wú)法理解它是如何工作的。我們稍后再對(duì)它做一個(gè)詳細(xì)介紹吧,現(xiàn)在我們用默認(rèn)配置文件把模塊編譯出來就成了。 第二種方法適合那些沒有完整PHP源碼的小盆友。雖然這個(gè)方法不怎么常用,但是為了保證完整性,我們也會(huì)對(duì)這種方法進(jìn)行介紹。 [使用make]: 使用標(biāo)準(zhǔn)機(jī)制進(jìn)行編譯:將模塊所在的文件夾復(fù)制到PHP源碼的ext文件夾下。運(yùn)行buildconf,將新模塊的配置項(xiàng)更新到configure腳本。 運(yùn)行完buildconf之后,使用configure --help你將會(huì)看到如下內(nèi)容 --enable-array_experiments BOOK: Enables array experiments --enable-call_userland BOOK: Enables userland module --enable-cross_conversion BOOK: Enables cross-conversion module --enable-first_module BOOK: Enables first module --enable-infoprint BOOK: Enables infoprint module --enable-reference_test BOOK: Enables reference test module --enable-resource_test BOOK: Enables resource test module --enable-variable_creation BOOK: Enables variable-creation module 你可以使用--enable-first_module 或 --enable-first_module=yes.將模塊置為可用 譯者注:在這里我沒有使用buildconf,而是用了phpize。。。windows上是沒有這個(gè)東西的,所以如果在win上還是用這個(gè)標(biāo)準(zhǔn)的方法進(jìn)行開發(fā)吧。還有一點(diǎn)需要特別注意的是如果你也使用phpize,一定要在.c文件開頭添加 #ifdef HAVE_CONFIG_H #include "config.h" #endif 這三行。否則你會(huì)遇到 PHP Warning: PHP Startup: Invalid library (maybe not a PHP library) 'xxx.so' in Unknown on line 0 [手動(dòng)編譯]: 手動(dòng)編譯只需要運(yùn)行如下命令: Action Command Compiling cc -fpic -DCOMPILE_DL_FIRST_MODULE=1 -I/usr/local/include -I. -I.. -I../Zend -c -o first_module.o first_module.c Linking cc -shared -L/usr/local/lib -rdynamic -o first_module.so first_module.o 譯者注:我在鏈接的時(shí)候使用了cc -bundle -flat_namespace -undefined suppress -o first_module.so first_module.o 如果你在鏈接的時(shí)候出現(xiàn)了問題,只需要用上面這條命令就可以了。因?yàn)槭褂昧?undefined suppress選項(xiàng),忽略了鏈接時(shí)找不到的外部文件,不用擔(dān)心,因?yàn)槟阍诿钚羞\(yùn)行php命令時(shí),libphp5.so會(huì)加載到內(nèi)存,幾乎一切你需要用到的函數(shù)都在內(nèi)存里了,所以運(yùn)行是木有任何問題的。 編譯指令使編譯器編譯時(shí)生成不定地址代碼。(顯示添加-fpic)而-DCOMPILE_DL_FIRST_MODULE則告訴編譯器生成動(dòng)態(tài)加載模塊。而后指定了一系列include路徑用于編譯源碼。 注:所有的相對(duì)路徑都是基于ext文件夾的。如果你是從別的文件夾編譯的,記得改變路徑。譯者的編譯命令:cc -fPIC -DCOMPILE_DL_FIRST_MODULE=1 -I/usr/local/include -I ../../../ -I ../../../main -I ../../../TSRM/ -I ../../../Zend -c -o first_module.o first_mod.c 相對(duì)路徑在ext/hello/src_first_mod 同時(shí)鏈接指令也指出鏈接器應(yīng)該將模塊作為動(dòng)態(tài)模塊鏈接。 注:由于將模塊作為靜態(tài)模塊直接編譯進(jìn)php的二進(jìn)制文件中的指令會(huì)非常非常非常長(zhǎng)所以我們就不在此做介紹了,感興趣的童鞋可以自學(xué)~~
信息發(fā)布:廣州名易軟件有限公司 http://m.jetlc.com
|