看了一下網上的文章,也有想學習一下PHP擴展的沖動,就試着寫了一下,剛剛調試成功,寫出來分享一下。
首先參考一下人家的文章 在Win32下用VC2008編譯PHP擴展:
以前在Linux下用C寫過PHP擴展,在Windows下是使用VC6來編譯的,近來有在Windows下用VC2008做PHP擴展的需要,找了一下資料,發現用VC2008也可以寫PHP擴展,現介紹步驟如下:
首先要下載PHP源代碼及Windows下的二進制壓縮包(需要解壓開后並正確配置php.ini,甚至Apache),因為在編譯擴展的過程中我們需要二進制壓縮包里的dev/php5ts.lib文件。接着使用PHP源代碼目錄下的ext/ext_skel_win32.php來生成擴展的骨架類。但ext_skel_win32.php中說要使用cygwin,但我機器上沒有裝cygwin,另外發現其中實際上只使用到了sh,而我機器上裝的MSYS里也有sh,應該可以用的吧,於是就將ext_skel_win32.php中的$cygwin_path變量設置成了MSYS的BIN目錄
$cygwin_path = 'c:\msys\1.0\bin';
然后設置環境變量,將解壓開的PHP二進制包目錄(包含php.exe的)以及MSYS的BIN目錄加入到PATH環境變量中。在控制台切換到PHP源碼ext目錄下執行ext_skel_win32.php腳本以生成骨架類:
php ext_skel_win32.php --extname=mytest
這樣就在PHP源碼的ext目錄下生成一個了一個mytest的目錄,里面有php_mytest.h, mytest.c和mytest.dsp,可以使用VC2008來打開mytest.dsp,它提示要轉換工程。
設置工程屬性頁中的C++->代碼生成->運行庫改為多線程DLL(/MD),將C++->高級->編譯為改為編譯為C代碼(/TC),鏈接器->附加庫目錄加一項PHP二進制包的dev目錄。
點生成->配置管理器->活動解決方案配置先Release_TS,平台為win32。
處理完這些后,還要修改PHP源碼中Zend/Zend.h,將
#include <stdio.h>
移動到
#ifdef ZEND_WIN32
# include "zend_config.w32.h"
# define ZEND_PATHS_SEPARATOR ';'
#elif defined(NETWARE)
# include <zend_config.h>
# define ZEND_PATHS_SEPARATOR ';'
#elif defined(__riscos__)
# include <zend_config.h>
# define ZEND_PATHS_SEPARATOR ';'
#else
# include <zend_config.h>
# define ZEND_PATHS_SEPARATOR ':'
#endif
的后面去。 還要修改zend_config.w32.h,將
#define vsnprintf _vsnprintf
這行注釋掉(否則編譯時會提示不能定義大小為0的常量數組和vsnprintf
相關的錯誤)。
這樣就可以正常編譯了(按Release_TS編譯),在PHP源碼目錄下的Release_TS目錄下生成了php_mytest.dll,將其拷貝到PHP二進制文件目錄下的ext目錄中,修改其php.ini文件,加上extension=php_mytest.dll,在命令行用php -i命令來查看模塊是否加載成功了:
mytest
mytest support => enabled
以上基本上沒用問題,只是到了PHP5.3.10后PHP開發組已經將上面的inlcude問題和下面的PRINTF問題解決了,不用改其他源代碼,直接編譯即可。
但是到了我這兒發現用這個擴展時的時候加載失敗,查看apache錯誤日志
Module compiled with build ID=API20060626,TS
PHP compiled with build ID=API20090626,TS,VC9
我用的 PHP Version 5.3.10 ,Compiler MSVC9 (Visual C++ 2008) 不清楚的自己phpinfo().一開始是我下載的C源代碼不對是5.2.17的,后來改到5.3.10后發現從VERY CD這個源下載的少了config.w32.h這個文件,於是我從5.2拷了個過來。發現還是有問題
Module compiled with build ID=API20090626,TS
PHP compiled with build ID=API20090626,TS,VC9
模塊沒有compiled ID,但我用的VS2010肯定是VC9的,說明C源代碼有問題,找了一下資料(點此),在main/config.w32.h中添加如下語句 #define PHP_COMPILER_ID "VC9"
好了,OK!
如圖

