程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> Hello World: 第一個PHP擴展

Hello World: 第一個PHP擴展

編輯:關於PHP編程

 

目標
創建一個名為 hello 的 PHP 擴展,並實現裡面唯一的函數 hello_world,作用是打印出 "Hello World" 字符串。

前提條件
一台已經安裝了 C 編譯器、PHP 運行環境的電腦,一個稱手的文本編輯器。
重要提示:不要試圖在 Windows 下寫 PHP 擴展,Visual C、MinGW 的編譯器都不好用,我曾經搗鼓了一個多星期也沒能在 Windows 下編譯成功過。所以至少要在一個 Unix 環境下進行。Mac 和各種 Linux 環境都可以。

下載 PHP 源代碼
先用 php -v 確定系統上的 PHP 版本,再到 php.net 上下載相應的源代碼包。解壓到某個目錄下,如 php5-5.3.5。源代碼目錄裡,ext 目錄下即是所有的 PHP 擴展所在的地方,其他的目錄暫時不必考慮。

生成 PHP 擴展的框架代碼
在 php5-5.3.5/ext 目錄下,有一個名為 ext_skel 的文件,這是用來創建擴展的一個簡便的工具。確保它有可執行權限(chmod u+x ext_skel),在終端下執行

./ext_skel --extname=hello

即會在 ext 目錄下創建一個 hello 的目錄,裡面是初始的骨架代碼。下一步的任務是創建 hello 擴展,並實現 hello_world 函數。

編輯 config.m4
用文本編輯器打開 ext/hello/config.m4,裡面有大量的注釋說明(以 dnl 開頭的行),基本上已經把很多問題說明白了。這裡要做的就是把

dnl PHP_ARG_ENABLE(hello, whether to enable hello support,
dnl Make sure that the comment is aligned:
dnl [  --enable-hello           Enable hello support])

這三行取消注釋。這樣在接下來的編譯時,可以用 ./configure --enable-hello 來編譯我們剛剛寫的擴展。

重新生成 configure
回到源代碼根目錄,運行 ./buildconf --force,會激活 configure --enable-hello 參數。如果你在運行 buildconf 時報下面的錯誤:

buildconf: Your version of autoconf likely contains buggy cache code.
           Running vcsclean for you.
           To avoid this, install autoconf-2.13.

請安裝 autoconf-2.13(ubuntu 懶人的用法)

sudo apt-get install autoconf2.13

編譯擴展
此時的 hello 擴展已經可以編譯了,雖然還沒有實現其中的 hello_world 函數。先編譯一下,確保沒有環境配置上的問題。

./configure --enable-hello
make

經過一段時間(其實是把整個 PHP 也編譯出來了),用

./sapi/cli/php -f ext/hello/hello.php

檢查一下擴展編譯情況。不出意外的話,應該提示

Functions available in the test extension:
confirm_hello_compiled

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

編寫 hello_world 函數
聲明函數:打開 ext/hello/php_hello.h,在

		PHP_MINIT_FUNCTION(hello);
PHP_MSHUTDOWN_FUNCTION(hello);
PHP_RINIT_FUNCTION(hello);
PHP_RSHUTDOWN_FUNCTION(hello);
PHP_MINFO_FUNCTION(hello);

後面添加

		PHP_FUNCTION(hello_world);

即在擴展的頭文件中聲明了 hello_world 的函數的原型。PHP_FUNCTION 是用來定義 PHP 函數的 C 語言宏。至於宏展開後的樣子,幾乎不用去想。只管用就可以了。

實現函數:打開 hello.c,在文件的末尾添加

		PHP_FUNCTION(hello_world){
	php_printf("Hello World");return;}

這裡即是 hello_world 函數的實現。php_printf 的作用是向 SAPI 輸出一段字符串,類似於 PHP 語言中的 echo。

接下來還需要將 hello_world 函數注冊到 zend_module_entry,這樣這個函數才能在 PHP 程序中變成“可見”的。找到

		const zend_function_entry hello_functions[]={
	PHP_FE(confirm_hello_compiled,	NULL)/* For testing, remove later. */{NULL, NULL, NULL}/* Must be the last line in hello_functions[] */};

將其修改為:

		const zend_function_entry hello_functions[]={
	PHP_FE(confirm_hello_compiled,	NULL)/* For testing, remove later. */
	PHP_FE(hello_world, NULL){NULL, NULL, NULL}/* Must be the last line in hello_functions[] */};

此時整個的 hello 擴展的代碼就編寫完了。最後再來 make 一下。

測試
在終端下運行 sapi/cli/php -r 'hello_world();echo "\n";',如果看到輸出“Hello World”,就成功了。

如何把擴展編譯成 .so 文件
上面編譯的結果是把 hello 擴展編譯進了 PHP 核心中。如果想要編譯成 .so 擴展,以便發布出去的話。需要使用

./configure --enable-hello=shared
make

這樣編譯完成後,會在 modules 目錄下生成 hello.so 文件。把它復制到你的 PHP 運行環境的 extension_dir 下就可以像其他擴展一樣使用了。需要注意的是 PHP 版本。如果你是在 PHP 5.3.5 的源代碼環境中編譯的擴展,則生成的 .so 文件只能用在 PHP 5.3.5 的運行環境中。

最後提一下,如果對 PHP 擴展有興趣,可以看看《Extending and Embedding PHP》這本書,作者還是個 MM。目前沒有中文版,英文電子版的自己搜。

摘自 lostwolf blog

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved