自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

淺析PHP Extension開(kāi)發(fā)基礎(chǔ)篇

開(kāi)發(fā) 后端
今天我們將介紹的是PHP當(dāng)中比較出名的PHP Extension開(kāi)發(fā)基礎(chǔ)篇,開(kāi)發(fā)環(huán)境是Ubuntu 10.04 + PHP 5.3.3。

PHP是當(dāng)前應(yīng)用非常廣泛的一門(mén)語(yǔ)言,從國(guó)外的Facebook、Twitter到國(guó)內(nèi)的淘寶、騰訊、百度再到互聯(lián)網(wǎng)上林林總總的各種大中小型網(wǎng)站都能見(jiàn)到它的身影。PHP的成功,應(yīng)該說(shuō)很大程度上依賴于其開(kāi)放的擴(kuò)展API機(jī)制和豐富的擴(kuò)展組件(PHP Extension),正是這些擴(kuò)展組件使得PHP從各種數(shù)據(jù)庫(kù)操作到XML、JSON、加密、文件處理、圖形處理、Socket等領(lǐng)域無(wú)所不能。有時(shí)候開(kāi)發(fā)人員可能需要開(kāi)發(fā)自己的PHP擴(kuò)展,當(dāng)前PHP5的擴(kuò)展機(jī)制是基于Zend API的,Zend API提供了豐富的接口和宏定義,加上一些實(shí)用工具,使得PHP擴(kuò)展開(kāi)發(fā)起來(lái)難度并不算特別大。本文將介紹關(guān)于PHP擴(kuò)展組件開(kāi)發(fā)的基本知識(shí),并通過(guò)一個(gè)實(shí)例展示開(kāi)發(fā)PHP擴(kuò)展的基本過(guò)程。

PHP擴(kuò)展組件的開(kāi)發(fā)過(guò)程在Unix和Windows環(huán)境下有所不同,但基本是互通的,本文將基于Unix環(huán)境(具體使用Linux)。閱讀本文需要簡(jiǎn)單了解Unix環(huán)境、PHP和C語(yǔ)言的一些基礎(chǔ)知識(shí),只要簡(jiǎn)單了解就行,我會(huì)盡量不涉及太過(guò)具體的操作系統(tǒng)和語(yǔ)言特性,并在必要的地方加以解釋,以便讀者閱讀。

本文的具體開(kāi)發(fā)環(huán)境為Ubuntu 10.04 + PHP 5.3.3。

下載PHP源代碼

要開(kāi)發(fā)PHP擴(kuò)展,第一步要下載PHP源代碼,因?yàn)槔锩嬗虚_(kāi)發(fā)擴(kuò)展需要的工具。我下載的是PHP最新版本5.3.3,格式為tar.bz2壓縮包。下載地址為:http://cn.php.net/get/php-5.3.3.tar.bz2/from/a/mirror。

下載后,將源代碼移動(dòng)到合適的目錄并解壓。解壓命令為:

  1. tar -jxvf 源碼包名稱  

若下載的是tar.gz壓縮包,解壓命令為

  1. tar -zxvf 源碼包名稱  

解壓后,在源代碼目錄中有個(gè)ext目錄,這里便是和PHP擴(kuò)展有關(guān)的目錄。進(jìn)入目錄后用ls查看,可以看到許多已經(jīng)存在的擴(kuò)展。下圖是在我的環(huán)境下查看的結(jié)果:

image

其中藍(lán)色的均是擴(kuò)展包目錄,其中可以看到我們很熟悉的mysql、iconv和gd等等。而ext_skel是Unix環(huán)境下用于自動(dòng)生成PHP擴(kuò)展框架的腳本工具,后面我們馬上會(huì)用到,ext_skel_win32.php是windows下對(duì)應(yīng)的腳本。

開(kāi)發(fā)自己的PHP擴(kuò)展——say_hello

下面我們開(kāi)發(fā)一個(gè)PHP擴(kuò)展:say_hello。這個(gè)擴(kuò)展很簡(jiǎn)單,只是接受一個(gè)字符串參數(shù),然后輸出“Hello xxx!”。這個(gè)例子只是為了介紹PHP擴(kuò)展組件的開(kāi)發(fā)流程,不承擔(dān)實(shí)際功能。

生成擴(kuò)展組件框架

PHP的擴(kuò)展組件開(kāi)發(fā)目錄和文件是有固定組織結(jié)構(gòu)的,你可以隨便進(jìn)入一個(gè)已有擴(kuò)展組件目錄,查看其所有文件,我想你一定眼花繚亂了。當(dāng)然你可以選擇手工完成框架的搭建,不過(guò)我相信你更希望有什么東西來(lái)幫你完成。上文提到的ext_skel腳本就是用來(lái)自動(dòng)構(gòu)建擴(kuò)展包框架的工具。ext_skel的完整命令為:

  1. ext_skel --extname=module [--proto=file] [--stubs=file] [--xml[=file]] [--skel=dir] [--full-xml] [--no-help]  

作為初學(xué)者,我們不必了解所有命令參數(shù),實(shí)際上,大多數(shù)情況下只需要提供第一個(gè)參數(shù)就可以了,也就是擴(kuò)展模塊的名字。因此,我們?cè)趀xt目錄中鍵入如下命令:

  1. /ext_skel --extname=say_hello  

(如果你希望詳細(xì)了解ext_skel的各項(xiàng)命令參數(shù),請(qǐng)參考這里

這時(shí)再用ls查看,會(huì)發(fā)現(xiàn)多了一個(gè)“say_hello”目錄,進(jìn)入這個(gè)目錄,會(huì)發(fā)現(xiàn)ext_skel已經(jīng)為我們建立好了say_hello的基本框架,如下圖:

image

如果你懶得弄清楚PHP擴(kuò)展包目錄結(jié)構(gòu)的全部?jī)?nèi)容,那么里面有三個(gè)文件你必須注意:

config.m4:這是Unix環(huán)境下的Build System配置文件,后面將會(huì)通過(guò)它生成配置和安裝。

php_say_hello.h:這個(gè)文件是擴(kuò)展模塊的頭文件。遵循C語(yǔ)言一貫的作風(fēng),這個(gè)里面可以放置一些自定義的結(jié)構(gòu)體、全局變量等等。

say_hello.c:這個(gè)就是擴(kuò)展模塊的主程序文件了,最終的擴(kuò)展模塊各個(gè)函數(shù)入口都在這里。當(dāng)然,你可以將所有程序代碼都塞到這里面,也可以遵循模塊化思想,將各個(gè)功能模塊放到不同文件中。

下面的內(nèi)容主要圍繞這三個(gè)文件展開(kāi)。

Unix Build System配置

開(kāi)發(fā)PHP擴(kuò)展組件的第一步不是寫(xiě)實(shí)現(xiàn)代碼,而是要先配置好Build System選項(xiàng)。由于我們是在Linux下開(kāi)發(fā),所以這里的配置主要與config.m4有關(guān)。

關(guān)于Build System配置這一塊,要是寫(xiě)起來(lái)能寫(xiě)一大堆,而且與Unix系統(tǒng)很多東西相關(guān),就算我有興趣寫(xiě)估計(jì)大家也沒(méi)興趣看,所以這里我們從略,只揀關(guān)鍵地方說(shuō)一下,關(guān)于config.m4更多細(xì)節(jié)可以參考這里。

打開(kāi)生成的config.m4文件,內(nèi)容大致如下:

  1. dnl $Id$    
  2. dnl config.m4 for extension say_hello    
  3. dnl Comments in this file start with the string 'dnl'.    
  4. dnl Remove where necessary. This file will not work    
  5.  dnl without editing.    
  6.  dnl If your extension references something external, use with:    
  7. dnl PHP_ARG_WITH(say_hello, for say_hello support,    
  8. dnl Make sure that the comment is aligned:    
  9. dnl [  --with-say_hello             Include say_hello support])    
  10. dnl Otherwise use enable:    
  11. dnl PHP_ARG_ENABLE(say_hello, whether to enable say_hello support,    
  12. dnl Make sure that the comment is aligned:    
  13. dnl [  --enable-say_hello           Enable say_hello support])    
  14. if test "$PHP_SAY_HELLO" != "no"; then   
  15.  dnl Write more examples of tests here...    
  16.  dnl # --with-say_hello -> check with-path    
  17.  dnl SEARCH_PATH="/usr/local /usr"     # you might want to change this    
  18.  dnl SEARCH_FOR="/include/say_hello.h"  # you most likely want to change this    
  19. dnl if test -r $PHP_SAY_HELLO/$SEARCH_FOR; then # path given as parameter    
  20.  dnl   SAY_HELLO_DIR=$PHP_SAY_HELLO    
  21.  dnl else # search default path list    
  22. dnl   AC_MSG_CHECKING([for say_hello files in default path])    
  23.  dnl   for i in $SEARCH_PATH ; do   
  24. dnl     if test -r $i/$SEARCH_FOR; then   
  25.  dnl       SAY_HELLO_DIR=$i    
  26.  dnl       AC_MSG_RESULT(found in $i)    
  27.  dnl     fi   
  28.  dnl   done   
  29.  dnl fi   
  30. dnl    
  31.  dnl if test -z "$SAY_HELLO_DIR"; then   
  32.  dnl   AC_MSG_RESULT([not found])    
  33.  dnl   AC_MSG_ERROR([Please reinstall the say_hello distribution])    
  34.  dnl fi   
  35.  dnl # --with-say_hello -> add include path    
  36.  dnl PHP_ADD_INCLUDE($SAY_HELLO_DIR/include)    
  37.  dnl # --with-say_hello -> check for lib and symbol presence    
  38.   dnl LIBNAME=say_hello # you may want to change this    
  39.    dnl LIBSYMBOL=say_hello # you most likely want to change this     
  40.  dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,    
  41.  dnl [    
  42.  dnl   PHP_ADD_LIBRARY_WITH_PATH($LIBNAME$SAY_HELLO_DIR/lib, SAY_HELLO_SHARED_LIBADD)    
  43.   dnl   AC_DEFINE(HAVE_SAY_HELLOLIB,1,[ ])    
  44.   dnl ],[    
  45.   dnl   AC_MSG_ERROR([wrong say_hello lib version or lib not found])    
  46.   dnl ],[    
  47.   dnl   -L$SAY_HELLO_DIR/lib -lm    
  48.   dnl ])    
  49.    dnl    
  50.    dnl PHP_SUBST(SAY_HELLO_SHARED_LIBADD)    
  51.    PHP_NEW_EXTENSION(say_hello, say_hello.c, $ext_shared)    
  52.  fi  

不要看這么多,因?yàn)樗幸?ldquo;dnl”開(kāi)頭的全是注釋,所以真正起作用沒(méi)幾行。這里需要配置的只有下面幾行:

  1.  dnl If your extension references something external, use with:    
  2.  dnl PHP_ARG_WITH(say_hello, for say_hello support,    
  3. dnl Make sure that the comment is aligned:    
  4. dnl [  --with-say_hello             Include say_hello support])    
  5. dnl Otherwise use enable:    
  6. dnl PHP_ARG_ENABLE(say_hello, whether to enable say_hello support,    
  7. dnl Make sure that the comment is aligned:    
  8.  dnl [  --enable-say_hello           Enable say_hello support])  

我想大家也都能看明白,意思就是“如果你的擴(kuò)展引用了外部組件,使用…,否則使用…”。我們的say_hello擴(kuò)展并沒(méi)有引用外部組件,所以將“Otherwise use enable”下面三行的“dnl”去掉,改為:

  1. dnl Otherwise use enable:    
  2.  PHP_ARG_ENABLE(say_hello, whether to enable say_hello support,    
  3.  Make sure that the comment is aligned:    
  4.  [  --enable-say_hello           Enable say_hello support])   
  5.  

保存,這樣關(guān)于Build System配置就大功告成了。

PHP Extension及Zend_Module結(jié)構(gòu)分析

以上可以看成是為開(kāi)發(fā)PHP擴(kuò)展而做的準(zhǔn)備工作,下面就要編寫(xiě)核心代碼了。上文說(shuō)過(guò),編寫(xiě)PHP擴(kuò)展是基于Zend API和一些宏的,所以如果要編寫(xiě)核心代碼,我們首先要弄清楚PHP Extension的結(jié)構(gòu)。因?yàn)橐粋€(gè)PHP Extension在C語(yǔ)言層面實(shí)際上就是一個(gè)zend_module_entry結(jié)構(gòu)體,這點(diǎn)可以從“php_say_hello.h”中得到證實(shí)。打開(kāi)“php_say_hello.h”,會(huì)看到里面有怎么一行:

  1. extern zend_module_entry say_hello_module_entry;  

say_hello_module_entry就是say_hello擴(kuò)展的C語(yǔ)言對(duì)應(yīng)元素,而關(guān)于其類型zend_module_entry的定義可以在PHP源代碼的“Zend/zend_modules.h”文件里找到,下面代碼是zend_module_entry的定義:

  1. typedef struct _zend_module_entry zend_module_entry;    
  2.  struct _zend_module_entry {    
  3.     unsigned short size;    
  4.      unsigned int zend_api;    
  5.    unsigned char zend_debug;    
  6.      unsigned char zts;    
  7.      const struct _zend_ini_entry *ini_entry;    
  8.      const struct _zend_module_dep *deps;    
  9.      const char *name;    
  10.      const struct _zend_function_entry *functions;    
  11.      int (*module_startup_func)(INIT_FUNC_ARGS);    
  12.      int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS);    
  13.      int (*request_startup_func)(INIT_FUNC_ARGS);    
  14.      int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS);    
  15.      void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS);    
  16.      const char *version;    
  17.      size_t globals_size;    
  18.  #ifdef ZTS    
  19.      ts_rsrc_id* globals_id_ptr;    
  20.  #else    
  21.      void* globals_ptr;    
  22.  #endif    
  23.      void (*globals_ctor)(void *global TSRMLS_DC);    
  24.      void (*globals_dtor)(void *global TSRMLS_DC);    
  25.      int (*post_deactivate_func)(void);    
  26.      int module_started;    
  27.      unsigned char type;    
  28.      void *handle;    
  29.      int module_number;    
  30.      char *build_id;    
  31.  };  

這個(gè)結(jié)構(gòu)體可能看起來(lái)會(huì)讓人有點(diǎn)頭疼,不過(guò)我還是要解釋一下里面的內(nèi)容。因?yàn)檫@就是PHP Extension的原型,如果不搞清楚,就沒(méi)法開(kāi)發(fā)PHP Extension了。當(dāng)然,我就不一一對(duì)每個(gè)字段進(jìn)行解釋了,只揀關(guān)鍵的、這篇文章會(huì)用到的字段說(shuō),因?yàn)樵S多字段并不需要我們手工填寫(xiě),而是可以使用某些預(yù)定義的宏填充。

第7個(gè)字段“name”,這個(gè)字段是此PHP Extension的名字,在本例中就是“say_hello”。

第8個(gè)字段“functions”,這個(gè)將存放我們?cè)诖藬U(kuò)展中定義的函數(shù)的引用,具體結(jié)構(gòu)不再分析,有興趣的朋友可以閱讀_zend_function_entry的源代碼。具體編寫(xiě)代碼時(shí)這里會(huì)有相應(yīng)的宏。

第9-12個(gè)字段分別是四個(gè)函數(shù)指針,這四個(gè)函數(shù)會(huì)在相應(yīng)時(shí)機(jī)被調(diào)用,分別是“擴(kuò)展模塊加載時(shí)”、“擴(kuò)展模塊卸載時(shí)”、“每個(gè)請(qǐng)求開(kāi)始時(shí)”和“每個(gè)請(qǐng)求結(jié)束時(shí)”。這四個(gè)函數(shù)可以看成是一種攔截機(jī)制,主要用于相應(yīng)時(shí)機(jī)的資源分配、釋放等相關(guān)操作。

第13個(gè)字段“info_func”也是一個(gè)函數(shù)指針,這個(gè)指針指向的函數(shù)會(huì)在執(zhí)行phpinfo()時(shí)被調(diào)用,用于顯示自定義模塊信息。

第14個(gè)字段“version”是模塊的版本。

(關(guān)于zend_module_entry更詳盡的介紹請(qǐng)參考這里

介紹完以上字段,我們可以看看“say_hello.c”中自動(dòng)生成的“say_hello_module_entry”框架代碼了。

  1. /* {{{ say_hello_module_entry    
  2.   */   
  3.  zend_module_entry say_hello_module_entry = {    
  4.  #if ZEND_MODULE_API_NO >= 20010901    
  5.      STANDARD_MODULE_HEADER,    
  6.  #endif    
  7.      "say_hello",    
  8.      say_hello_functions,    
  9.      PHP_MINIT(say_hello),    
  10.      PHP_MSHUTDOWN(say_hello),    
  11.      PHP_RINIT(say_hello),       /* Replace with NULL if there's nothing to do at request start */   
  12.      PHP_RSHUTDOWN(say_hello),   /* Replace with NULL if there's nothing to do at request end */   
  13.      PHP_MINFO(say_hello),    
  14.  #if ZEND_MODULE_API_NO >= 20010901    
  15.      "0.1"/* Replace with version number for your extension */   
  16.  #endif    
  17.      STANDARD_MODULE_PROPERTIES    
  18.  };    
  19.  /* }}} */  

首先,宏“STANDARD_MODULE_HEADER”會(huì)生成前6個(gè)字段,“STANDARD_MODULE_PROPERTIES ”會(huì)生成“version”后的字段,所以現(xiàn)在我們還不用操心。而我們關(guān)心的幾個(gè)字段,也都填寫(xiě)好或由宏生成好了,并且在“say_hello.c”的相應(yīng)位置也生成了幾個(gè)函數(shù)的框架。這里要注意,幾個(gè)宏的參數(shù)均為“say_hello”,但這并不表示幾個(gè)函數(shù)的名字全為“say_hello”,C語(yǔ)言中也不可能存在函數(shù)名重載機(jī)制。實(shí)際上,在開(kāi)發(fā)PHP Extension的過(guò)程中,幾乎處處都要用到Zend里預(yù)定義的各種宏,從全局變量到函數(shù)的定義甚至返回值,都不能按照“裸寫(xiě)”的方式來(lái)編寫(xiě)C語(yǔ)言,這是因?yàn)镻HP的運(yùn)行機(jī)制可能會(huì)導(dǎo)致命名沖突等問(wèn)題,而這些宏會(huì)將函數(shù)等元素變換成一個(gè)內(nèi)部名稱,但這些對(duì)程序員都是透明的(除非你去閱讀那些宏的代碼),我們通過(guò)各種宏進(jìn)行編程,而宏則為我們處理很多內(nèi)部的東西。

寫(xiě)到這里,我們的任務(wù)就明了了:第一,如果需要在相應(yīng)時(shí)機(jī)處理一些東西,那么需要填充各個(gè)攔截函數(shù)內(nèi)容;第二,編寫(xiě)say_hello的功能函數(shù),并將引用添加到say_hello_functions中。

編寫(xiě)phpinfo()回調(diào)函數(shù)

因?yàn)閟ay_hello擴(kuò)展在各個(gè)生命周期階段并不需要做操作,所以我們只編寫(xiě)info_func的內(nèi)容,上文說(shuō)過(guò),這個(gè)函數(shù)將在phpinfo()執(zhí)行時(shí)被自動(dòng)調(diào)用,用于顯示擴(kuò)展的信息。編寫(xiě)這個(gè)函數(shù)會(huì)用到四個(gè)函數(shù):

php_info_print_table_start()——開(kāi)始phpinfo表格。無(wú)參數(shù)。

php_info_print_table_header()——輸出表格頭。第一個(gè)參數(shù)是整形,指明頭的列數(shù),然后后面的參數(shù)是與列數(shù)等量的(char*)類型參數(shù)用于指定顯示的文字。

php_info_print_table_row()——輸出表格內(nèi)容。第一個(gè)參數(shù)是整形,指明這一行的列數(shù),然后后面的參數(shù)是與列數(shù)等量的(char*)類型參數(shù)用于指定顯示的文字。

php_info_print_table_end()——結(jié)束phpinfo表格。無(wú)參數(shù)。

下面是“say_hello.c”中需要編寫(xiě)的info_func的具體代碼:

  1. /* {{{ PHP_MINFO_FUNCTION    
  2.  */   
  3. PHP_MINFO_FUNCTION(say_hello)    
  4. {    
  5.     php_info_print_table_start();    
  6.     php_info_print_table_header(2, "say_hello support""enabled");    
  7.     php_info_print_table_row(2, "author""Zhang Yang"); /* Replace with your name */   
  8.     php_info_print_table_end();    
  9.     /* Remove comments if you have entries in php.ini    
  10.     DISPLAY_INI_ENTRIES();    
  11.     */   
  12. }    
  13. /* }}} */  
可以看到我們編寫(xiě)了兩行內(nèi)容、組件是否可用以及作者信息。

編寫(xiě)核心函數(shù)

編寫(xiě)核心函數(shù),總共分為三步:1、使用宏P(guān)HP_FUNCTION定義函數(shù)體;2、使用宏ZEND_BEGIN_ARG_INFO和ZEND_END_ARG_INFO定義參數(shù)信息;3、使用宏P(guān)HP_FE將函數(shù)加入到say_hello_functions中。下面分步說(shuō)明。

使用宏P(guān)HP_FUNCTION定義函數(shù)體

  1. PHP_FUNCTION(say_hello_func)    
  2. {    
  3.     char *name;    
  4.     int name_len;    
  5.     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE)    
  6.     {    
  7.         return;    
  8.     }    
  9.     php_printf("Hello %s!", name);    
  10.    RETURN_TRUE;    
  11. }  

上文說(shuō)過(guò),編寫(xiě)PHP擴(kuò)展時(shí)幾乎所有東西都不能裸寫(xiě),而是必須使用相應(yīng)的宏。從上面代碼可以清楚看到這一點(diǎn)。總體來(lái)說(shuō),核心函數(shù)代碼一般由如下幾部分構(gòu)成:

定義函數(shù),這一步通過(guò)宏P(guān)HP_FUNCTION實(shí)現(xiàn),函數(shù)的外部名稱就是宏后面括號(hào)里面的名稱。

聲明并定義局部變量。

解析參數(shù),這一步通過(guò)zend_parse_parameters函數(shù)實(shí)現(xiàn),這個(gè)函數(shù)的作用是從函數(shù)用戶的輸入棧中讀取數(shù)據(jù),然后轉(zhuǎn)換成相應(yīng)的函數(shù)參數(shù)填入變量以供后面核心功能代碼使用。zend_parse_parameters的第一個(gè)參數(shù)是用戶傳入?yún)?shù)的個(gè)數(shù),可以由宏“ZEND_NUM_ARGS() TSRMLS_CC”生成;第二個(gè)參數(shù)是一個(gè)字符串,其中每個(gè)字母代表一個(gè)變量類型,我們只有一個(gè)字符串型變量,所以第二個(gè)參數(shù)是“s”;最后各個(gè)參數(shù)需要一些必要的局部變量指針用于存儲(chǔ)數(shù)據(jù),下表給出了不同變量類型的字母代表及其所需要的局部變量指針。

image

參數(shù)解析完成后就是核心功能代碼,我們這里只是輸出一行字符,php_printf是Zend版本的printf。

最后的返回值也是通過(guò)宏實(shí)現(xiàn)的。RETURN_TRUE宏是返回布爾值“true”。

使用宏ZEND_BEGIN_ARG_INFO和ZEND_END_ARG_INFO定義參數(shù)信息

參數(shù)信息是函數(shù)所必要部分,這里不做深究,直接給出相應(yīng)代碼:

  1. ZEND_BEGIN_ARG_INFO(arginfo_say_hello_func, 0)    
  2. ZEND_END_ARG_INFO()  

如需了解具體信息請(qǐng)閱讀相關(guān)宏定義。

使用宏P(guān)HP_FE將函數(shù)加入到say_hello_functions中

最后,我們需要將剛才定義的函數(shù)和參數(shù)信息加入到say_hello_functions數(shù)組里,代碼如下:

  1. const zend_function_entry say_hello_functions[] = {    
  2.      PHP_FE(say_hello_func, arginfo_say_hello_func)    
  3.     {NULL, NULL, NULL}    
  4. };  

這一步就是通過(guò)PHP_EF宏實(shí)現(xiàn),注意這個(gè)數(shù)組最后一行必須是{NULL, NULL, NULL} ,請(qǐng)不要?jiǎng)h除。

下面是編寫(xiě)完成后的say_hello.c全部代碼:

  1.  /*    
  2.    +---------------------------------------------------------------------+    
  3. | PHP Version 5                                                        |    
  4.    +----------------------------------------------------------------------+    
  5.    | Copyright (c) 1997-2010 The PHP Group                                |    
  6.    +----------------------------------------------------------------------+    
  7.   | This source file is subject to version 3.01 of the PHP license,      |    
  8.  | that is bundled with this package in the file LICENSE, and is        |    
  9.   | available through the world-wide-web at the following url:           |    
  10.   | http://www.php.net/license/3_01.txt                                  |    
  11.   | If you did not receive a copy of the PHP license and are unable to   |    
  12.    | obtain it through the world-wide-web, please send a note to          |    
  13.    | license@php.net so we can mail you a copy immediately.               |    
  14.    +----------------------------------------------------------------------+    
  15.    | Author:                                                              |    
  16.   +----------------------------------------------------------------------+    
  17.  */   
  18.  /* $Id: header 297205 2010-03-30 21:09:07Z johannes $ */   
  19.  #ifdef HAVE_CONFIG_H    
  20. #include "config.h"    
  21.  #endif    
  22. #include "php.h"    
  23. #include "php_ini.h"    
  24.  #include "ext/standard/info.h"    
  25.  #include "php_say_hello.h"    
  26.  /* If you declare any globals in php_say_hello.h uncomment this:    
  27.  ZEND_DECLARE_MODULE_GLOBALS(say_hello)    
  28.  */   
  29.  /* True global resources - no need for thread safety here */   
  30. static int le_say_hello;    
  31.  /* {{{ PHP_FUNCTION    
  32.   */   
  33. PHP_FUNCTION(say_hello_func)    
  34.  {    
  35.      char *name;    
  36.      int name_len;    
  37.   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE)    
  38.    {    
  39.        return;    
  40.      }    
  41.     php_printf("Hello %s!", name);    
  42.    RETURN_TRUE;    
  43.  }    
  44. ZEND_BEGIN_ARG_INFO(arginfo_say_hello_func, 0)    
  45.  ZEND_END_ARG_INFO()    
  46.  /* }}} */   
  47.  /* {{{ say_hello_functions[]    
  48.   *    
  49.   * Every user visible function must have an entry in say_hello_functions[].    
  50.  */   
  51.  const zend_function_entry say_hello_functions[] = {    
  52.      PHP_FE(say_hello_func, arginfo_say_hello_func)    
  53.      {NULL, NULL, NULL}  /* Must be the last line in say_hello_functions[] */   
  54.  };    
  55.  /* }}} */   
  56. /* {{{ say_hello_module_entry    
  57.   */   
  58. zend_module_entry say_hello_module_entry = {    
  59.  #if ZEND_MODULE_API_NO >= 20010901    
  60.      STANDARD_MODULE_HEADER,    
  61.  #endif    
  62.     "say_hello",    
  63.     say_hello_functions,    
  64.     NULL,    
  65.     NULL,    
  66.      NULL,    
  67.      NULL,    
  68.     PHP_MINFO(say_hello),    
  69.  #if ZEND_MODULE_API_NO >= 20010901    
  70.     "0.1"/* Replace with version number for your extension */   
  71.  #endif    
  72.     STANDARD_MODULE_PROPERTIES    
  73.  };    
  74.  /* }}} */   
  75. #ifdef COMPILE_DL_SAY_HELLO    
  76.  ZEND_GET_MODULE(say_hello)    
  77. #endif    
  78.  /* {{{ PHP_MINFO_FUNCTION    
  79.   */   
  80. PHP_MINFO_FUNCTION(say_hello)    
  81.  {    
  82.      php_info_print_table_start();    
  83.      php_info_print_table_header(2, "say_hello support""enabled");    
  84.     php_info_print_table_row(2, "author""Zhang Yang"); /* Replace with your name */   
  85.    php_info_print_table_end();    
  86.     /* Remove comments if you have entries in php.ini    
  87.     DISPLAY_INI_ENTRIES();    
  88.    */   
  89. }    
  90.  /* }}} */  

編譯并安裝擴(kuò)展

在say_hello目錄下輸入下面命令:

  1. /usr/bin/phpize    
  2. ./configure    
  3. make   
  4. make install  

這樣就完成了say_hello擴(kuò)展的安裝(如果沒(méi)有報(bào)錯(cuò)的話)。

這時(shí)如果你去放置php擴(kuò)展的目錄下,會(huì)發(fā)現(xiàn)多了一個(gè)say_hello.so的文件。如下圖所示:

image

下面就是將其加入到php.ini配置中,然后重啟Apache(如果需要的話)。這些都是PHP基本配置的內(nèi)容,我就不詳述了。

擴(kuò)展測(cè)試

如果上面順利完成,這時(shí)運(yùn)行phpinfo(),應(yīng)該能看到如下信息:

image

這說(shuō)明擴(kuò)展已經(jīng)安裝成功了。然后我們編寫(xiě)一個(gè)測(cè)試用PHP腳本:

  1. php    
  2.  say_hello_func('Zhang Yang');    
  3.  ?>  

執(zhí)行這個(gè)腳本,結(jié)果如下:

image說(shuō)明擴(kuò)展已經(jīng)正常工作了。

總結(jié)

這篇文章主要用示例方法介紹PHP Extension的開(kāi)發(fā)基礎(chǔ)。在PHP的使用中,也許是因?yàn)樾枰С中碌慕M件(如新的數(shù)據(jù)庫(kù)),又或是業(yè)務(wù)需要或性能需要,幾乎都會(huì)遇到需要開(kāi)發(fā)PHP擴(kuò)展的地方。后續(xù)如果有機(jī)會(huì),我會(huì)寫(xiě)文章介紹一些關(guān)于擴(kuò)展開(kāi)發(fā)較為深入的東西,如擴(kuò)展模塊生命周期、INI使用以及編寫(xiě)面向?qū)ο蟮臄U(kuò)展模塊等等。

原文鏈接:http://www.cnblogs.com/leoo2sk/archive/2010/12/09/talk-about-php-ext-develop-basic.html

【編輯推薦】

  1. 讓PHP開(kāi)發(fā)者事半功倍的十大技巧
  2. PHP開(kāi)發(fā)者不可不知的五件事
  3. 優(yōu)秀的PHP開(kāi)發(fā)者是怎樣煉成的?
  4. 十款PHP開(kāi)發(fā)者值得關(guān)注的編碼工具 

 

責(zé)任編輯:彭凡 來(lái)源: 博客園
相關(guān)推薦

2009-01-16 14:08:42

PHP開(kāi)發(fā)Web應(yīng)用執(zhí)行效率

2011-09-22 15:15:40

2009-09-03 10:41:46

Windows Cac

2009-11-17 09:13:21

PHP運(yùn)算符

2011-08-18 10:02:47

iPhone SDKOpenFlow

2011-08-18 09:52:13

iPhone SDKUIPageContr

2010-06-02 15:24:15

PHP+MySQL

2018-08-16 09:29:26

2009-03-23 10:53:00

PHP5.3新特性PHP5.3PHP5

2019-10-31 08:00:00

機(jī)器學(xué)習(xí)人工智能AI

2009-08-06 18:18:27

ASP.NET控件開(kāi)發(fā)ASP.NET復(fù)合控件

2009-07-22 10:03:11

iBATIS Resu

2009-08-06 13:08:23

ASP.NET控件開(kāi)發(fā)

2024-06-07 13:11:44

2023-04-07 09:20:55

2010-11-03 10:31:51

PHP魔術(shù)方法

2009-12-11 10:59:48

PHP函數(shù)extrac

2009-08-27 11:43:31

C#語(yǔ)法

2009-09-23 11:07:11

Hibernate基礎(chǔ)

2009-11-30 16:40:38

PHP object對(duì)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)