每一個php擴充的建置至少需要兩個檔案: 一個configuration檔, 它告訴編譯期要建置哪些檔案以及需要什麼外部的函式庫, 還需要至少一個原始檔, 它執行實際的工作.
剖析擴展
實際上, 通常會有第二個或第三個設定檔, 以及一個或多個頭檔. 對於你的第一個擴充, 你需要新增每種類型的一個檔案並使用它們工作.
設定檔
要開始了, 首先在你的php原始碼目錄樹的ext/目錄下建立名為sample的目錄. 實際上這個新的目錄可以放在任何地方, 但是為了在本章後面演示win32和靜態構建選項, 我們還是先建立在源代碼目錄下吧.
下一步, 進入這個目錄, 創建一個名為config.m4的檔案, 鍵入下面內容:
PHP_ARG_ENABLE(sample, [Whether to enable the "sample" extension], [ enable-sample Enable "sample" extension support]) if test $PHP_SAMPLE != "no"; then PHP_SUBST(SAMPLE_SHARED_LIBADD) PHP_NEW_EXTENSION(sample, sample.c, $ext_shared) fi
這是./configure時能夠呼叫enable-sample選項的最低要求.PHP_ARG_ENABLE的第二個參數將在./configure處理過程中到達這個擴充功能的設定檔時顯示. 第三個參數將在終端使用者執行./configure --help時顯示為幫助資訊.
有沒有想過為什麼有的擴充配置使用enable-extname,而有的擴充則使用with-extname? 功能上兩者沒有區別. 實際上, enable表示啟用這個特性不需要其他任何第三方庫, 相比之下, with則表示要使用這個特性還有其他先決條件
現在, 你的sample擴充不需要和其他函式庫連結, 因此只需要使用enable版本. 在第17章"外部函式庫", 我們將介紹使用with並指示編譯器使用額外的CFLAGS和LDFLAGS設定.
如果終端使用者使用enable-sample選項呼叫了./configure, 那麼本地的環境變數$PHP_SAMPLE, 將被設定為yes. PHP_SUBST()是標準autoconf的AC_SUBST()巨集的php修改版, 它在將擴展構建為共享模組時需要.
#最後但並不是不重要的, PHP_NEW_EXTENSION()定義了模組並列舉了所有必須作為擴展的一部分編譯的原始檔. 如果需要多個檔案, 它可以在第二個參數中使用空格分隔列舉, 例如:
PHP_NEW_EXTENSION(sample, sample.c sample2.c sample3.c, $ext_shared)
最後一個參數是對應於PHP_SUBST(SAMPLE_SHARED_LIBADD)命令的, 在構建共享模組的時候同樣需要它.
頭文件
當使用C開發的時候,將資料的類型定義放到外部的頭檔中隔離起來, 由來源檔案包含是常見的做法. 儘管php並不要求這樣, 但是這樣做在模組增長到不能放到單一來源檔案時是有簡化作用的.
在你的php_sample.h頭檔中, 以下面內容開始:
#ifndef PHP_SAMPLE_H /* 防止重复包含 */ #define PHP_SAMPLE_H /* 定义扩展的属性 */ #define PHP_SAMPLE_EXTNAME "sample" #define PHP_SAMPLE_EXTVER "1.0" /* 在php源码树外面构建时引入配置选项 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* 包含php的标准头文件 */ #include "php.h" /* 定义入口点符号, Zend在加载这个模块的时候使用 */ extern zend_module_entry sample_module_entry; #define phpext_sample_ptr &sample_module_entry #endif /* PHP_SAMPLE_H */
這個頭檔完成了兩個主要的任務: 如果擴充使用phpize工具建構(本書通常都用這種方式), 那麼HAVE_CONFG_H就是已定義的, 這樣config.h就會被正常的包含進來. 無論擴展怎樣編譯, 都會從php源碼樹中包含php.h. 這個頭文件中包含了php源碼中存取大部分PHPAPI要使用的其他頭檔.
接下來, 你的擴充使用的zend_module_entry結構定義為外部的, 這樣當這個模組使用extension=xxx載入時, 就可以被Zend使用dlopen和dlsym()取到.
頭檔中還會包含一些預處理, 定義將在原始檔中使用的資訊.
原始碼
#最後, 最重要的你需要在sample.c中建立一個簡單的原始碼骨架:
#include "php_sample.h" zend_module_entry sample_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif PHP_SAMPLE_EXTNAME, NULL, /* Functions */ NULL, /* MINIT */ NULL, /* MSHUTDOWN */ NULL, /* RINIT */ NULL, /* RSHUTDOWN */ NULL, /* MINFO */ #if ZEND_MODULE_API_NO >= 20010901 PHP_SAMPLE_EXTVER, #endif STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_SAMPLE ZEND_GET_MODULE(sample) #endif
以上是如何寫一個php擴展的詳細內容。更多資訊請關注PHP中文網其他相關文章!