用 C or C++ 開發PHP擴展模塊

如果要用C++ 來開發,只需要extern "C" {}將其C的頭文件和庫定義包含起來就可以,C++可以直接使用C的庫,

----------------------------------------------------

得到一份PHP源碼,我這裏用的是 php-5.3.0.tar.gz
解壓
進入到 ext 目錄下。
$./ext_skel --extname=jason_php_module      //jason_php_module 爲自定義的模塊名
進入到生成的目錄 jason_php_module 目錄中,有一些文件和目錄。

config.m4           // linux下編譯配置文件
config.w32          // win32 下編譯配置文件
CREDITS  
EXPERIMENTAL  
jason_php_module.c           
jason_php_module.php     
php_jason_php_module.h           
tests

可以根據提示來修改config.m4文件,這裏有幾個重要的宏命令如下:

    * dnl 是註釋;
    * PHP_ARG_WITH 或者 PHP_ARG_ENABLE 指定了PHP擴展模塊的工作方式,前者意味着不需要第三方庫,後者正好相反;
    * PHP_REQUIRE_CXX 用於指定這個擴展用到了C++;
    * PHP_ADD_INCLUDE 指定PHP擴展模塊用到的頭文件目錄;
    * PHP_CHECK_LIBRARY 指定PHP擴展模塊PHP_ADD_LIBRARY_WITH_PATH定義以及庫連接錯誤信息等;
    * PHP_ADD_LIBRARY(stdc++,"",EXTERN_NAME_LIBADD)用於將標準C++庫鏈接進入擴展
    * PHP_SUBST(EXTERN_NAME_SHARED_LIBADD) 用於說明這個擴展編譯成動態鏈接庫的形式;
    * PHP_NEW_EXTENSION 用於指定有哪些源文件應該被編譯,文件和文件之間用空格隔開; 

ext_skel默認生成的模塊框架是針對C的, 
如果我們要使用C++進行PHP擴展, 那除以上的PHP_REQUIRE_CXX, PHP_ADD_LIBRARY兩個宏必需外,還要把jason_php_module.c改名成jason_php_module.cpp。 
需要注意的是,在config.m4裏面可以使用類似的Makefile語法,片段如下:

  PHP_REQUIRE_CXX()
  INCLUDES="$INCLUDES `mysql_config --cflags`"
  PHP_ADD_LIBRARY(stdc++, "", EXTRA_LDFLAGS)
  EXTRA_LDFLAGS="$EXTRA_LDFLAGS `mysql_config --libs` -lmemcached"
  AC_CHECK_HEADERS([mysql/mysql.h])
  CPPFILE="ext_name.cpp antiForbitWord.cpp antiBaseDict.cpp Trie.cpp Logger.cpp antiEncodeConverter.cpp strnormalize.cpp"
  PHP_NEW_EXTENSION(ext_name, $CPPFILE, $ext_shared)


----------------------------------------------------
修改php_jason_php_module.h 文件
由於TSRM.h這個文件所包含的函數和類都是用純C語言寫的,故應該使用extern來說明如下:

  extern "C" {
  #ifdef ZTS
  #include "TSRM.h"
  #endif
  }

如果該php_ext_name.h頭文件或者ext_name.cpp文件用到了C++語言中的一些容器或者一些函數,則需要在頭文件中包含相應的c++庫的頭文件,否則會出現找不到相應的C++函數錯誤。 

----------------------------------------------------
修改jason_php_module.cpp這個cpp文件。

由於config.h、php.h、php_ini.h和ext/standard/info.h中包含的函數和類如TSRM.h一樣,都是用純C語言寫的,所以也需要用extern說明如下:

  extern "C" {
  #ifdef HAVE_CONFIG_H
  #include "config.h"
  #endif

  #include "php.h"
  #include "php_ini.h"
  #include "ext/standard/info.h"
  }

而 #include "php_ext_name.h" 這句則已經不需要包含在extern "C"內,另外,ZEND_GET_MODULE這個宏命令也是需要特別申明如下:

  #ifdef COMPILE_DL_EXT_NAME
  BEGIN_EXTERN_C()
  ZEND_GET_MODULE(ext_name)
  END_EXTERN_C()
  #endif

總之,把一些C寫的庫或轟用兼容的方式給解決

---------------------------------------------------
現在可以去編譯擴展模塊了。如果你想把它編譯成靜態模塊(把它做爲PHP的一個部分編譯進PHP中去),去到PHP的根目錄$PHP_HOME,刪去 configure 文件和運行buildconf (譯:需要libtool的支持)。

然後用你平常用的參數運行 configure 並加上--enable-php5cpp 項。運行 make clean, make, make install ,並完成其它的一些必要操作,如:重新編譯Apache。

如果你想用動態鏈接庫的方式編譯擴展模塊,到你的模塊的目錄下,運行phpize 命令(假設你已經安裝了PEAR),它會爲你的模塊創建一個 configure 腳本。然後運行configure, make 和 make install。如果你想讓你的模塊自動加載,你要修改php.ini 以加載正確的文件。如:加上類似的一行:extension=php5cpp.so 。

$phpize
$./configure 
$make

注意:

在運行 Phpize命令之後 如果出現錯誤

Configuring for:
PHP Api Version:         20041225
Zend Module Api No:      20060613
Zend Extension Api No:   220060519
Cannot find autoconf. Please check your autoconf installation and the
$PHP_AUTOCONF environment variable. Then, rerun this script.

根據網上的解決辦法是:

# fetch http://ftp.gnu.org/gnu/m4/m4-1.4.9.tar.gz  

# tar -zvxf m4-1.4.9.tar.gz # cd m4-1.4.9/

# ./configure && make && make install # cd ../

# fetch http://ftp.gnu.org/gnu/autoconf/autoconf-2.62.tar.gz

# tar -zvxf autoconf-2.62.tar.gz # cd autoconf-2.62/

# ./configure && make && make install

這樣就可以了 

用phpize生成configure執行文件後,可以用./configure --help查看幫助信息,修改config.m4文件可以修改configure的幫助信息。每次修改了config.m4文件,需要使用清除臨時文件命令phpize --clean來完成消除configure。 

現在你的PHP擴展模塊已經編譯好了。試着運行一下在模塊目錄下自動生成的php5cpp.php ,看看是不是一切正常?:)

------------------------------------
怎麼使用寫好的擴展就不細說了
調試的時候,可以在PHP 裏用 dl('jason_php_module.so');
應用中,可以根據情況編譯進PHP中,或配置進PHP中。

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