糯米文學吧

位置:首頁 > 計算機 > php語言

php 5.x 擴充套件開發要點

php語言3.17W

導語:php 5.x 擴充套件開發要點,最近因專案需要開發了一個windows dll形式的php擴充套件,實現訪問soap webservice。下面就由小編為大家介紹一下php 5.x 擴充套件開發要點,歡迎大家閱讀

php 5.x 擴充套件開發要點

開發環境是visual studio 2010(VC10)。測試用了 xampp-win32-5.6.28-1-VC11-installer。

  為什麼不直接用php soap擴充套件

php確實有一個php_soap的官方擴充套件,對soap webservice操作進行了封裝。在本案例中,此前博主已經用gSOAP對某個web service功能進行了封裝,釋出了兩個DLL訪問ws介面,實現資料查詢和載入。php擴充套件是在gSOAP開發的DLL基礎上,做進一步的封裝。

除此之外,還可以藉助gSOAP封裝的DLL,開發其他語言的擴充套件,例如python module。良好的功能劃分可以提高複用性,減少工作重複。

  安裝XAMPP

安裝的時候,至少選擇安裝apache和php。

  基本程式碼結構

php以extension的.形式提供擴充套件。位於擴充套件功能底層核心的是zend引擎。

windows需要包含標頭檔案

#include "zend_config.w32.h"

/* include standard header */

#include "php.h"

PHP擴充套件的開發,主要通過一組巨集定義,完成擴充套件的框架構建。例如

PHP_MINIT_FUNCTION(CustomExt); // module載入。通常是apache啟動的時候

PHP_MSHUTDOWN_FUNCTION(CustomExt); //module解除安裝。通常是apache關閉的時候。

PHP_RINIT_FUNCTION(CustomExt); //一般對應一個php指令碼啟動的時候。

PHP_RSHUTDOWN_FUNCTION(CustomExt); // 一般對應一個php指令碼退出的時候。

而PHP擴充套件中的函式,通過PHP_FUNCTION定義。例如

PHP_FUNCTION(paradb_wsquery_new);

PHP_FUNCTION(paradb_wsquery_prepare);

PHP_FUNCTION(paradb_wsquery_query);

PHP_FUNCTION(paradb_anytype_print);

PHP_FUNCTION(paradb_wsload_new);

PHP_FUNCTION(paradb_wsload_prepare);

PHP_FUNCTION(paradb_wsload_load);

  核心資料結構

zend_module_entry CustomExtModule_module_entry = {

STANDARD_MODULE_HEADER,

"CustomExt Module",

CustomExtModule_functions,

PHP_MINIT(CustomExt),

PHP_MSHUTDOWN(CustomExt),

PHP_RINIT(CustomExt),

PHP_RSHUTDOWN(CustomExt),

NULL,

NO_VERSION_YET, STANDARD_MODULE_PROPERTIES

};

這個結構引用了擴充套件需要的所有東西。PHP核心引擎通過這個結構找到擴充套件,呼叫相關的函式。

  記憶體管理

基本原則是在哪個層次申請的,就在哪個層次釋放。

在PHP層面,不要用malloc()函式,用php提供的emalloc()或者pemalloc()。這種方法申請的記憶體在php擴充套件程式碼中,不必顯式釋放。php框架對這些記憶體進行了統一的管理。PHP核心可以確保託管記憶體不會發生記憶體洩露而危及平臺的執行穩定。

php擴充套件可以呼叫第三方DLL中定義的函式,返回一個新的類例項。那麼這個類例項被建立和被析構的地方,都應該位於第三方DLL,例如不要在php層面用emalloc()為第三方DLL的物件申請記憶體。

如果使用EG(persistent_list)導致空指標訪問違例,博主建議在MINIT函式中自定義一個hashtable。

資源如何定義和返回

為了封裝c++結構,在PHP中使用自己定義的c++類,需要在php擴充套件中,定義資源resource。每一種資源型別對應著一個唯一的int。例如

int le_paradb_wsquery, le_paradb_xsdany;

#define PHP_PARADB_WSQUERY_RES_NAME "paradb wsquery"

#define PHP_GSOAP_XSD_ANYTYPE_RES_NAME "gsoap xsdany"

#define PHP_PARADB_WSLOAD_RES_NAME "paradb wsload"

在MINIT函式中,對資源進行定義。主要是定義了對應的解構函式。例如

le_paradb_wsquery = zend_register_list_destructors_ex(php_paradb_wsquery_dtor, NULL, PHP_PARADB_WSQUERY_RES_NAME, module_number);

PHP_FUNCTION(paradb_wsquery_new)

{

WsQuery *q;

char *name;

int name_len;

zval* p;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {

RETURN_FALSE;

}

if (name_len < 1) {

php_error_docref(NULL TSRMLS_CC, E_WARNING, "No endpoint given, WsQuery resource not created.");

RETURN_FALSE;

}

paradbc_wsquery_init2(&q, name);

php_printf("[paradb_wsquery_new %p]

", q);

ZEND_REGISTER_RESOURCE(return_value, q, le_paradb_wsquery);

}

通過ZEND_REGISTER_RESOURCE巨集,一個結構被返回到PHP指令碼。實際是一個指標,其內容是完全透明的。

返回的這個資源,PHP指令碼在後續可以使用。

PHP_FUNCTION(paradb_wsquery_query2)

{

WsQuery *q;

zval *zq;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zq) == FAILURE) {

RETURN_FALSE;

}

ZEND_FETCH_RESOURCE(q, WsQuery*, &zq, -1, PHP_PARADB_WSQUERY_RES_NAME, le_paradb_wsquery);

......

}

通過ZEND_FETCH_RESOURCE巨集,PHP擴充套件程式碼得到這個resource,從zval得到實際的結構例項。

  其他事項

解決http 80埠被佔用的問題

windows system後臺程序可能佔用了本地80埠,到XAMPP控制面板,config,修改,改成 Listen 8080,監聽8080埠。

PHP原始碼下載

下載對應當前版本的PHP原始碼。例如

解壓為 C:xamppphp-5.6.28

下載依賴包

需要下載bison。可將相關檔案拷貝到windows系統目錄。

生成需要的標頭檔案

利用VC命令列環境,在PHP原始碼目錄做一次configure操作。

Setting environment for using Microsoft Visual Studio 2010 x86 tools.

C:Program Files (x86)Microsoft Visual Studio 10.0VC>cd /d C:xamppphp-5.6.28

C:xamppphp-5.6.28>

C:xamppphp-5.6.28>set PATH=C:Program Filesisonin;%PATH%

C:xamppphp-5.6.28>

nmake可以不做。這裡主要是為了生成構建PHP擴充套件所需的標頭檔案。

注意:建議使用與xampp完全相同的VC版本,否則需要修改config.w32.h中的PHP_COMPILER_ID與xampp的完全一致。例如apache 報告錯誤

PHP Warning: PHP Startup: CustomExt Module: Unable to initialize module

Module compiled with build ID=API20131226,TS,VC10

PHP compiled with build ID=API20131226,TS,VC11

These options need to match

解決辦法是手動修改 main/config.w32.h

#define PHP_COMPILER_ID "VC11"

-END-

標籤:PHP 5x 擴充套件