開發PHP擴展模塊

首先,我們需要PHP源碼包,如果沒有就下一個吧,反正很近,就 http://www.php.net了。:D

Linux/BSD下的步驟

[yingyuan@research src]$ pwd
/home/yingyuan/data1/src
[yingyuan@research src]$ ls
php-4.3.4.tar.gz
[yingyuan@research src]$ tar zxvf php-4.3.4.tar.gz
...
[yingyuan@research src]$ cd php-4.3.4

現在我們到了PHP源代碼根目錄,下文簡稱爲$PHP_SRC_HOME。
仔細看看,這裏有這麼幾個子目錄是需要注意的:main, TSRM, Zend。這些子目錄包含了編譯擴展模塊必要的頭文件。

[yingyuan@research php-4.3.4]$ cd ext
[yingyuan@research ext]$ ls
... ext_skel ext_skel_win32.php ...

這個目錄有很多子目錄,每個子目錄都是PHP的一個擴展模塊。此外還有兩個文件:ext_skel是一個shell腳本,運行它能生成PHP擴展模塊的框架;ext_skel_win32.php,用來生成Windows下的PHP擴展模塊框架。偶心中竊喜,ext_skel_win32.php,哈,開發Windows下的PHP擴展模塊變得如此Easy。話雖如此,可是別忘了裝CygWin(http://www.cygwin.com/)這個胖的可愛的小助理。像我這樣心疼時間的人當然不會裝了,所以通常我是在Linux/BSD下用ext_skel生成框架,然後拷貝到Windows下用的。

諸位,我們開始幹活了。先看看我們在哪裏:

[yingyuan@research ext]$ pwd
/home/yingyuan/data1/src/php-4.3.4/ext

假設我們要寫一個很恢宏的PHP擴展模塊,模塊名叫 myext,則運行如下命令:

[yingyuan@research ext]$ ./ext_skel --extname=myext           
Creating directory myext
Creating basic files: config.m4 .cvsignore myext.c php_myext.h CREDITS EXPERIMENTAL tests/001.phpt myext.php [done].
To use your new extension, you will have to execute the following steps:
1.  $ cd ..
2.  $ vi ext/myext/config.m4
3.  $ ./buildconf
4.  $ ./configure --[with|enable]-myext
5.  $ make
6.  $ ./php -f ext/myext/myext.php
7.  $ vi ext/myext/myext.c
8.  $ make
Repeat steps 3-6 until you are satisfied with ext/myext/config.m4 and
step 6 confirms that your module is compiled into PHP. Then, start writing
code and repeat the last two steps as often as necessary.

根據提示,ext_skel替我們生成了模塊myext的骨架:目錄myext, 目錄myext下的文件config.m4、php_myext.h、myext.c、myext.php。至於其他文件我就得考慮了。

根據提示,我們做如下操作。

[yingyuan@research ext]$ cd ..
[yingyuan@research php-4.3.4]$ vi ext/myext/config.m4

關於m4文件的撰寫說明,這裏沒空共享給各位了,感興趣可以上 http://www.gnu.org/software/m4/manual/index.html 瞧瞧。

這裏有必要說明一下:
PHP編譯的時候要激活某個擴展模塊,有兩種方式,--with-xxxx和--enable-xxxx。差別在於前者可以引用外部相關文件,比如--with-mysql=/usr/local/mysql等等,而後者不能。這要根據你的需要,比如你要寫一個xml parser擴展,想在你的擴展代碼中引用外部系統的libxml,那麼爲了保證你的代碼總是能成功找到必要的libxml文件,就可以用--with-xxxx方式,讓用戶在編譯的時候指定libxml文件位置。
我們這裏用--enable-xxxx吧,因爲我們的myext確實沒什麼好引用的。

找到這麼幾行:

dnl PHP_ARG_ENABLE(myext, whether to enable myext support,
dnl Make sure that the comment is aligned:
dnl [  --enable-myext           Enable myext support])
if test "$PHP_MYEXT" != "no"; then
  dnl Write more examples of tests here...
...

改成:

PHP_ARG_ENABLE(myext, whether to enable myext support,
[  --enable-myext           Enable myext support])
if test "$PHP_MYEXT" == "yes"; then
  dnl Write more examples of tests here...
...

首先需要告訴PHP自動編譯系統不要對我們的擴展模塊視而不見,然後還需要在用戶明確要求enable我們的擴展模塊時才編譯。這就是以上修改的原因。

接着往下走:

[yingyuan@research php-4.3.4]$ ./buildconf
You should not run buildconf in a release package.
use buildconf --force to override this check.

系統抱怨說發行版本不能運行 buildconf,嘿嘿,我們強制運行:

[yingyuan@research php-4.3.4]$ ./buildconf --force
[yingyuan@research php-4.3.4]$ ./configure --help | grep myext
  --enable-myext           Enable myext support

從這個輸出可以看到我們的擴展模塊已經可用。

[yingyuan@research php-4.3.4]$ ./configure --enable-myext
...
[yingyuan@research php-4.3.4]$ make
...
[yingyuan@research php-4.3.4]$ ./sapi/cli/php -f ext/myext/myext.php 
Functions available in the test extension:
confirm_myext_compiled

Congratulations! You have successfully modified ext/myext/config.m4. 
Module myext is now compiled into PHP.

至此我們的demo函數已經奏效,接下來聽你們提問了:

Q1:我一定要make整個PHP代碼包纔可以make我的擴展模塊嗎?
A1:不用。你甚至不用修改config.m4文件。方法是手工編譯擴展模塊:
切換到目錄$PHP_SRC_HOME/ext
cc -fpic -DCOMPILE_DL=1 -DCOMPILE_DL_module_name -I/usr/local/include -I. -I.. -I../Zend -I../main -I../TSRM -c -o
cc -shared -L/usr/local/lib -rdynamic -o

本例中,

[yingyuan@research php-4.3.4]$ cd ext
[yingyuan@research ext]$ cc -fpic -DCOMPILE_DL=1 -DCOMPILE_DL_MYEXT -I/usr/local/include /
-I. -I.. -I../Zend -I../main -I../TSRM -c -o myext/myext.o myext/myext.c
[yingyuan@research ext]$ cc -shared -L/usr/local/lib -rdynamic -o myext/myext.so myext/myext.o

Q2:怎樣爲我的擴展模塊生成GUN AutoMake兼容的自動編譯文件
A2:利用$PHP_SRC_HOME/scrīpts/phpize。其實$PHP_SRC_HOME/scrīpts/下面還有別的有意思的東西。:D

Q3:怎樣用C++寫PHP擴展模塊
A3:這涉及到C和C++的名稱轉換問題,需要對C定義的頭文件用extern "C"包圍起來,本文不提供更詳細的信息。

Windows下的步驟

我們需要前面所說的PHP源代碼包,還需要php4ts.lib。後者可以在PHP的Windows安裝包中找到。這裏我們談談用VC 6如何開發PHP擴展模塊。不要有恐懼心理,微軟讓事情變得更簡單而不是更復雜。
我們新建一個Win32 Dylamic-Link Library項目myext,選擇Empty Project。然後把ext_skel生成的兩個文件php_myext.h、myext.c添加到項目中,做如下設定:

打開菜單項 Build >> Set Active Configuration...,這裏有兩個項可供選擇:Win32 Release和Win32 Debug,我們這裏選擇Win32 Release。

打開菜單項 Tools >> Options,選擇Directories屬性頁.在這裏可以對頭文件和庫文件的搜索路徑進行設置.
在Show directories for 下拉列表中選擇Library files, 把php4ts.lib所在的目錄添加進去.比如C:/PHP/PHP-4.3.11.
在Show directories for 下拉列表中選擇Include files,把PHP頭文件所在的路徑加上,比如:
C:/PHP/PHP-4.3.4
C:/PHP/PHP-4.3.4/main
C:/PHP/PHP-4.3.4/TSRM
C:/PHP/PHP-4.3.4/Zend

打開菜單項 Project >> Settings...,選擇C/C++屬性頁。
在Category下拉列表中選擇Code Generation,在Use run-time library下拉列表中選擇Multithreaded DLL(對應於Win32 Release版本)或者Debug Multithreaded DLL(對應於Win32 Debug版本)。
在Category下拉列表中選擇Preprocessor,在Preprocessor defines裏添加 ZEND_DEBUG=0,COMPILE_DL_SIPLOOKUP,ZTS=1,ZEND_WIN32,PHP_WIN32。如果你在調試你的工程,可把ZEND_DEBUG設置爲1.這裏也可以在Additional include directories設置搜索頭文件,不過因爲我們已經在以上的步驟設置了,就沒有必要了。最後我們在Project Options中添加選項 /Tc,這告訴編譯器把我們的源文件當C程序處理。

在菜單項 Project >> Settings...中,選擇Link屬性頁。
在Object/library modules中把php4ts.lib添加進去。
然後就可以進行Build,生成我們的DLL文件。如果有錯誤不用着急,相信自己,相信Google。^_^

幾點建議

PHP手冊是開發擴展模塊最好的教材,如果有心於斯就一定要看看,這個不能偷懶了;
PHP擴展模塊開發網站 http://pecl.php.net 可以去看看;
如果不知道該如何着手,比如不知道怎樣創建Resource,或者從函數中返回值,最快的方式就是翻翻$PHP_SRC_HOME/ext下的擴展模塊源代碼,很多東西都可以參考的。

 
發佈了41 篇原創文章 · 獲贊 5 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章