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

Linux 下PHP擴展開發系列:二. 一個典型的擴展開發

編輯:關於PHP編程

 

看完前言中所說的一些內容後,各位應該對PHP擴展開發有個籠統的了解了,可能有些人會覺得開發擴展很麻煩很復雜,實際上並非如此,這一篇我們就快速進入角色,開發出我們的第一個擴展。


 

一、編譯PHP

開發之前還需要先准備好PHP源碼並編譯,過程如下:

 -zxvf php-..-.

我使用的是php5.3.9,解壓後,我們進入了PHP源碼目錄,然後我們直接編譯並增加php.ini:

./configure --prefix=/usr/local/webserver/php --enable-fastcgi --enable-fpm --enable- &&  
 /home/soft/php-./php.ini-development /usr/local/webserver/php/lib/php.ini

編譯完成,我沒有靜態編譯其他擴展,但是開啟了debug,這個後面會用到。然後修改php.ini中對應的項,這裡就不細說了。

現在把PHP相關加入環境變量中,省去後面很多工作:

vim /root/.bash_profile

我是使用root,其他不同用戶修改對應用戶目錄下的.bask_profile文件,在文件中的PATH後面加入:/usr/local/webserver/php/bin/,類似下面這樣:

PATH=$PATH:$HOME/bin:/usr/local/webserver/php/bin/

環境變量設置好了,我們查看下PHP版本:

 OK,編譯工作完成,讓我們繼續。

 

二、典型開發流程

一個典型的擴展開發流程如下圖:

 

 三、擴展功能定義

-2147483648 到 2147483647,與32位系統相同。

 

四、正式開發  

   

   

 

cd /home/soft/php-./ext

 

    然後了解下PHP提供的擴展骨架工具ext_skel生成骨架,ext_skel的用法如下:

./ext_skel --extname=module [--proto=] [--stubs=] [--xml[=--skel=] [--full-xml] [--no---extname=--proto=       --stubs=       generate only  stubs  
  --xml              generate xml documentation to be added to phpdoc---skel=         path to the skeleton directory(設置骨架生成的目錄,不設置該項則默認在ext/--full-xml         generate xml documentation  a self---no-help          don
                     and helper functions to test  the module compiled (生成的代碼中不顯示各種幫助注釋)

    這次我們准備用到兩個選項,--extname=myip 即定義擴展的名稱,而--proto=myip.pro則是定義擴展的函數原型,首先我們生成擴展函數原型文件:

vim myip.pro

    加入以下內容:

 ip2long32( ip)

    這意味著我們的擴展中有一個函數,返回值為int型,輸入為string。

    這時候執行以下命令生成擴展骨架:

./ext_skel --extname=myip --proto=myip.pro

    OK,這時候你會發現在當前PHP擴展目錄下生成了一個子目錄myip,進入myip看下:



    你會發現生成了一堆文件,如下圖:

    此時我們就可以進行第二步了。

    2. 修改config.m4

    關於config.m4文件的功能,我們留到後面的文章中在詳細進行說明,現在只說明要做什麼。

    使用vim編輯config.m4:

vim config.m4

    將16至18行行首的dnl去掉,如下:

    具體這樣做的原因在後面的文章中會說明,這邊我們直接退出並保存config.m4,繼續進入下一步。

    3. 編碼

    重頭戲來啦,終於可以進入myip.c中進行功能的編碼了,一起歡呼下吧!

vim myip.c

   找到下圖所示的位置:

   圖中就是擴展骨架工具根據我們提供的函數原型生成的對應函數,此處有幾個需要注意的地方:

   1. PHP_FUNCTION:是PHP核心定義的一個宏,與ZEND_FUNCTION相同,用於定義擴展函數,實際生成的函數名稱為zif_ip2long32。

   2. zend_parse_parameters:由於PHP為弱類型語言,而C是強類型,因此需要使用該函數用於接收PHP傳入的參數,並進行一定的類型轉換,將PHP的變量轉為C語言能夠辨認的類型。

      zend_parse_parameters函數的原型如下:

zend_parse_parameters( num_args TSRMLS_CC,  *type_spec, …);

      參數說明:

  •       num_args:傳遞給函數的參數個數。通常的做法是使用宏 ZEND_NUM_ARGS()。
  •       TSRMLS_CC:線程安全,總是傳遞TSRMLS_CC宏。 詳解:http://www.54chen.com/php-tech/what-is-tsrmls_cc.html
  •       type_spec:第三個參數是一個字符串,指定了函數期望的參數類型
  •       ...:需要隨參數值更新的變量列表]

  • type_spec是格式化字符串,其常見的含義如下: 參數   代表著的類型 b   Boolean l   Integer 整型 d   Floating point 浮點型 s   String 字符串 r   Resource 資源 a   Array 數組 o   Object instance 對象 O   Object instance of a specified type 特定類型的對象 z   Non-specific zval 任意類型~ Z   zval**類型 f   表示函數、方法名稱

   我們將該函數修改為如下內容:

 *ip = argc = (zend_parse_parameters(argc TSRMLS_CC, , &ip, &ip_len) ==, &ip1, &ip2, &ip3, &= (int32_t)((ip1 << ) | (ip2 << ) | (ip3 << ) |

    功能完成了,這邊有個RETURN_LONG(ip_int32)比較特殊,這也是PHP內核提供的宏,用於返回值給PHP,具體說明如下:

設置返回值並且結束函數        設置返回值             宏返回類型和參數
RETURN_LONG(l)           RETVAL_LONG(l)           整數
RETURN_BOOL(b)          RETVAL_BOOL(b)           布爾數(1或0)
RETURN_NULL()           RETVAL_NULL()           NULL
RETURN_DOUBLE(d)        RETVAL_DOUBLE(d)        浮點數
RETURN_STRING(s, dup)       RETVAL_STRING(s, dup)       字符串。如果dup為1,引擎會調用estrdup()重復s,使用拷貝。如果dup為0,就使用s
RETURN_STRINGL(s, l, dup)     RETVAL_STRINGL(s, l, dup)    長度為l的字符串值。與上一個宏一樣,但因為s的長度被指定,所以速度更快。
RETURN_TRUE           RETVAL_TRUE            返回布爾值true。注意到這個宏沒有括號。
RETURN_FALSE           RETVAL_FALSE           返回布爾值false。注意到這個宏沒有括號。
RETURN_RESOURCE(r)        RETVAL_RESOURCE(r)       資源句柄。

    編碼完成了,保存並退出,然後我們可以開始編譯了。

    4. 編譯

/configure --with-php-config=/usr/local/webserver/php/bin/php- &&  

    不出意外的話編譯完成後會有如下提示:

Installing shared extensions:     /usr/local/webserver/php/lib/php/extensions/debug-non-zts-/

    進入該目錄看下是否已經有myip.so,有的話最後我們就可以修改php.ini載入該so文件

    5. 修改php.ini

cd /usr/local/webserver/php/

    修改extension_dir,並加入 extension = myip.so

extension_dir = "/usr/local/webserver/php/lib/php/extensions/debug-non-zts-20090626/"= myip.so

    退出保存,並重啟php,如果是使用Phpfpm的話可以執行如下命令:

 -USR2 ` /usr/local/webserver/php/var/run/php-fpm.pid`

    看下擴展是否正常載入:

[root@tm977 lib]# php -m|

    說明已經正常載入了,最後我們測試下擴展函數吧!

    6. 測試

php -r 
(--r   
()

    如上所示,ip2long32輸出的是32位有符號整數,而ip2long輸出的是64位無符號整數,大功告成!

 

五、小結

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