編寫自己的php擴充函數
php程式寫的時間長了,自然對他所提供的功能瞭如指掌,他所提供的一大堆功能,真是覺得很好用,但有時候會發現php也缺少一些功能,自己總是會產生為php添加一些自訂的功能的想法。久而久之,終於今天憋不住了,開始動手研究如何添加。
下載一個php的原始碼包,這裡使用的是php 4.0.5版,解壓縮後會看到php的根目錄下會有README.EXT_SKEL這樣一個文件,打開詳細閱讀了一下,發現了一個非常好用的工具,這個工具可以幫你建立一個空的php擴展,然後你向裡面添加相應的程式碼就可以完成你自己的功能擴展了。下面我們就來介紹如何使用這個工具。
先轉移你的目錄到php的目錄下的ext目錄,如果你只需要一個基本的擴展框架的話,執行下面的命令:
./ ext_skel --extname=module_name
module_name是你自己可以選擇的擴充模組的名字,例如我選擇的my_module。執行工具後會自動在ext目錄下建立你選擇的module_name名字的目錄,裡面已經產生了相關的程式碼,這些程式碼只需要調整config.m4檔案中的三行註解就可以正常的編譯帶這個自訂擴充模組的php了。在php的根目錄執行下列操作就可以得到。
./buildconf
./configure --enable-module_name
make
我來示範建立在下面示範建立架構的全過程,為了更有效果,我們來完成一個php的擴充功能,在php中呼叫這個功能可以在web頁面中顯示hello world這個經典字。
在php目錄下的ext目錄中,執行下面的命令
./ext_skel --extname=my_module
得到回饋結果:
Creating directory my_module
Creating basic files: config.m4 Makefile.in .cvsignore my_module.c php_my_module.h tests/001.phpt my_module.php [done].
1. $ cd ..
2. $ vi ext/my_ule/config.m
4. $ ./configure --[with|enable]-my_module
5. $ make
5. $ make
5. $ make
5. $ make
6. f ext/my_module/my_module.php
7. $ vi ext/my_module/my_module.c
8. $ make
8. $ make
-6 until you are satisfied with ext/my_module/config.m4 and
step 6 confirms that your module is compiled into PHP. Then, start writing
often as necessary.
如果你能看懂上面的東西,那就照著去做。如果不是太明白的話,按照我下面的提示來做也可以。
cd my_module
首先進入my_module目錄
vi config.m4
使用文字編輯器開啟config.m4文件,檔案內容大致如下:
使用文字編輯器開啟config.m4文件,檔案內容大致如下:
dnl $Id$
擴充my_module 的dnl config.m4
dnl 不要忘記呼叫PHP_EXTENSION(my_module)
文件中的註解以字串“dnl”開頭。
dnl 必要時刪除。如果不進行編輯,此文件將無法
dnl。
dnl 如果您的擴充程式引用了外在內容,請使用:
dnl PHP_ARG_WITH(my_module, 對於🎜>
dnl PHP_ARG_WITH(my_module, 對
dnl 確保註解對齊:
dnl [ --with-my_module 包含my_module 支援])
🎜>
dnl PHP_ARG_ENABLE(my_module, 是否啟用my_module支持,
dnl 確保註釋對齊:
dnl [ --enable-my_module 啟用my_module 支持])
if test "$PHP_MY_MODULE" != "no";然後
dnl 如果您不打算測試任何外部內容,例如
dnl 頭文件、庫或其中的頭文件、庫或其中的函數的存在,只需取消註解
dnl 以下行即可準備好了。
dnl 在這裡寫更多測試範例...
PHP_EXTENSION(my_module, $ext_shared)
Fi
你自己的選擇將
dnl PHP_ARG_WITH(my_module, for my_module support,
dnl 確保註解對齊:
修改成
PHP_ARG_WITH(my_module, for my_module support,
確保註解對齊:
[ 🎜 >
或將
dnl PHP_ARG_ENABLE(my_module, 是否啟用my_module 支援,
dnl 確保註解對齊:
dnl [ )
修改成
PHP_ARG_ENABLE(my_module, 是否啟用my_module 支援,
確保註解已對齊:
一般我會選擇睡眠,然後儲存退出。如果你對 vi 文字編輯器的操作有困難的話,請參考相應的說明文章,這裡就不再詳細描述了。
Vi my_module.c
將檔案其中的以下程式碼進行修改
/* 每個使用者可見的函式都必須在my_module_functions[].
*/
function_entry my_module_functions[] = {
PHP_FE(say_hello, PHP_FE(confirm_my_module_compiled, NULL ) /* 為了測試,稍後刪除。 */
{NULL, NULL, NULL} /* 必須是my_module_functions[] 中的最後一行*/
PHP_FUNCTION(say_hello)
{
zend_printf("hello worldn");檔案退出
vi php_my_module.h
在檔案中PHP_FUNCTION(confirm_my_module_compiled); 🎜>
儲存檔案退出
退回到php的根目錄下,執行下面的指令
./buildconf
. --enable-my_module
make
如果一切順利的話,我們現在已經將擴充模組my_module編譯到php裡面了。下面我們寫的程式碼進行測試
Say_hello();
?>
儲存檔案為say_yh.
?>
儲存檔案為say_hhello> >在php的根目錄接下來運行
./php –q say_hello.php
正常情況下會顯示
hello world
表示我們的第一個擴展正常的運行了!
解釋一下上面做的操作,ext_skel產生一些框下文件,我們需要修改以下文件
my_module.c 模組的主程式
my_module.c 模組的主程式
php_my_module.h 擴充模組的頭檔
config.m4 設定檔
主程式中描述了php模組模組的聲明,模組中有多少個函數,各個函數的作用,在phpinfo函數中顯示什麼內容,模組初始化做準備,結束做準備都會在這個文件裡進行描述。我們在上面只是添加了一個函數say_hello,並且描述了say_hello函數的具體內容,呼叫zend_printf系統函數在php中列印字串。
在對應的頭檔中宣告了say_hello這個函數,從而完成了我們預期的功能。下面我們會寫一個更複雜的擴展,創造一個帶有參數的php擴展函數,根據給入的參數,顯示hello world, xxxx。 Xxxx代表輸入的字串內容,例如我的名字yorgo。
Vi my_module.c
修改最後的say_hello函數內容如下:
PHP_FUNCTION(say_hello函數內容如下:
PHP_FUNCTION(say_hello) zval **yourname;
if (ZEND_NUM_ARGS() !
{
WRONG_PARAM_COUNT;
}
}
盤退出。
退回php的根目錄,運行
make
修改say_hello.php為
);
?>
保存退出後運行
./php –q say_hello.php
得出結果
php
得出結果
php
得出結果
php
得出結果
表示我們這次的修改也成功了,可以改變say_hello中的參數,看看動態的效果。
這裡主要解釋上面修改的函式內容,由於say_hello函式需要有參數引入,所以在my_module.c中的say_hello函式主要在進行參數的處理,將php中引用say_hello時所填入的參數內容正確的傳遞到my_module.c中的say_hello處理函數。為此,程式中添加了這麼幾行。
zval **yourname;
if (ZEND_NUM_ARGS() != 1
zend_get_parameters_ex(1, &yourname) == FAILURE)
>WRONG_PARAM_COUNT;
}
zend_printf("hello world, %sn", Z_STRVAL_PP(yourname));
zval **yourname;
初始化一個參數的指標
ZEND_NUM_ARGS()
得到傳遞過來得參數數量,並且判斷如果不為1的時候表示有問題,報錯。
zend_get_parameters_ex(1, &yourname)
將剛剛初始化的指標指向傳遞過來的參數,如果不成功則報錯。
Z_STRVAL_PP(yourname)
處理指標指向的參數並取得實際儲存的值。
(待續)