php 5.x 擴(kuò)展開(kāi)發(fā)要點(diǎn)
導(dǎo)語(yǔ):php 5.x 擴(kuò)展開(kāi)發(fā)要點(diǎn),最近因項(xiàng)目需要開(kāi)發(fā)了一個(gè)windows dll形式的php擴(kuò)展,實(shí)現(xiàn)訪問(wèn)soap webservice。下面就由小編為大家介紹一下php 5.x 擴(kuò)展開(kāi)發(fā)要點(diǎn),歡迎大家閱讀!
開(kāi)發(fā)環(huán)境是visual studio 2010(VC10)。測(cè)試用了 xampp-win32-5.6.28-1-VC11-installer。
為什么不直接用php soap擴(kuò)展
php確實(shí)有一個(gè)php_soap的官方擴(kuò)展,對(duì)soap webservice操作進(jìn)行了封裝。在本案例中,此前博主已經(jīng)用gSOAP對(duì)某個(gè)web service功能進(jìn)行了封裝,發(fā)布了兩個(gè)DLL訪問(wèn)ws接口,實(shí)現(xiàn)數(shù)據(jù)查詢和加載。php擴(kuò)展是在gSOAP開(kāi)發(fā)的DLL基礎(chǔ)上,做進(jìn)一步的封裝。
除此之外,還可以借助gSOAP封裝的DLL,開(kāi)發(fā)其他語(yǔ)言的擴(kuò)展,例如python module。良好的功能劃分可以提高復(fù)用性,減少工作重復(fù)。
安裝XAMPP
安裝的時(shí)候,至少選擇安裝apache和php。
基本代碼結(jié)構(gòu)
php以extension的形式提供擴(kuò)展。位于擴(kuò)展功能底層核心的是zend引擎。
windows需要包含頭文件
#include "zend_config.w32.h"
/* include standard header */
#include "php.h"
PHP擴(kuò)展的開(kāi)發(fā),主要通過(guò)一組宏定義,完成擴(kuò)展的框架構(gòu)建。例如
PHP_MINIT_FUNCTION(CustomExt); // module加載。通常是apache啟動(dòng)的時(shí)候
PHP_MSHUTDOWN_FUNCTION(CustomExt); //module卸載。通常是apache關(guān)閉的時(shí)候。
PHP_RINIT_FUNCTION(CustomExt); //一般對(duì)應(yīng)一個(gè)php腳本啟動(dòng)的`時(shí)候。
PHP_RSHUTDOWN_FUNCTION(CustomExt); // 一般對(duì)應(yīng)一個(gè)php腳本退出的時(shí)候。
而PHP擴(kuò)展中的函數(shù),通過(guò)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);
核心數(shù)據(jù)結(jié)構(gòu)
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
};
這個(gè)結(jié)構(gòu)引用了擴(kuò)展需要的所有東西。PHP核心引擎通過(guò)這個(gè)結(jié)構(gòu)找到擴(kuò)展,調(diào)用相關(guān)的函數(shù)。
內(nèi)存管理
基本原則是在哪個(gè)層次申請(qǐng)的,就在哪個(gè)層次釋放。
在PHP層面,不要用malloc()函數(shù),用php提供的emalloc()或者pemalloc()。這種方法申請(qǐng)的內(nèi)存在php擴(kuò)展代碼中,不必顯式釋放。php框架對(duì)這些內(nèi)存進(jìn)行了統(tǒng)一的管理。PHP核心可以確保托管內(nèi)存不會(huì)發(fā)生內(nèi)存泄露而危及平臺(tái)的運(yùn)行穩(wěn)定。
php擴(kuò)展可以調(diào)用第三方DLL中定義的函數(shù),返回一個(gè)新的類實(shí)例。那么這個(gè)類實(shí)例被創(chuàng)建和被析構(gòu)的地方,都應(yīng)該位于第三方DLL,例如不要在php層面用emalloc()為第三方DLL的對(duì)象申請(qǐng)內(nèi)存。
如果使用EG(persistent_list)導(dǎo)致空指針訪問(wèn)違例,博主建議在MINIT函數(shù)中自定義一個(gè)hashtable。
資源如何定義和返回
為了封裝c++結(jié)構(gòu),在PHP中使用自己定義的c++類,需要在php擴(kuò)展中,定義資源resource。每一種資源類型對(duì)應(yīng)著一個(gè)唯一的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函數(shù)中,對(duì)資源進(jìn)行定義。主要是定義了對(duì)應(yīng)的析構(gòu)函數(shù)。例如
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);
}
通過(guò)ZEND_REGISTER_RESOURCE宏,一個(gè)結(jié)構(gòu)被返回到PHP腳本。實(shí)際是一個(gè)指針,其內(nèi)容是完全透明的。
返回的這個(gè)資源,PHP腳本在后續(xù)可以使用。
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);
......
}
通過(guò)ZEND_FETCH_RESOURCE宏,PHP擴(kuò)展代碼得到這個(gè)resource,從zval得到實(shí)際的結(jié)構(gòu)實(shí)例。
其他事項(xiàng)
解決http 80端口被占用的問(wèn)題
windows system后臺(tái)進(jìn)程可能占用了本地80端口,到XAMPP控制面板,config,修改httpd.conf,改成 Listen 8080,監(jiān)聽(tīng)8080端口。
PHP源碼下載
下載對(duì)應(yīng)當(dāng)前版本的PHP源碼。例如
php-5.6.28.tar.gz
http://php.net/distributions/php-5.6.28.tar.gz
解壓為 C:xamppphp-5.6.28
下載依賴包
需要下載bison。可將相關(guān)文件拷貝到windows系統(tǒng)目錄。
http://gnuwin32.sourceforge.net/packages/bison.htm
生成需要的頭文件
利用VC命令行環(huán)境,在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>buildconf.bat
C:xamppphp-5.6.28>set PATH=C:Program Filesisonin;%PATH%
C:xamppphp-5.6.28>configure.bat
nmake可以不做。這里主要是為了生成構(gòu)建PHP擴(kuò)展所需的頭文件。
注意:建議使用與xampp完全相同的VC版本,否則需要修改config.w32.h中的PHP_COMPILER_ID與xampp的完全一致。例如apache error.log報(bào)告錯(cuò)誤
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
解決辦法是手動(dòng)修改 main/config.w32.h
#define PHP_COMPILER_ID "VC11"
-END-
【php 5.x 擴(kuò)展開(kāi)發(fā)要點(diǎn)】相關(guān)文章:
PHP開(kāi)發(fā)安全保護(hù)的要點(diǎn)09-17
PHP擴(kuò)展程序講解09-30
php下zmq擴(kuò)展安裝-208-17
PHP常用開(kāi)發(fā)技巧09-19
怎樣編寫(xiě)一個(gè)獨(dú)立的PHP擴(kuò)展09-18
linux下用phpize給PHP動(dòng)態(tài)添加擴(kuò)展09-10
PHP開(kāi)發(fā)安全的技巧09-12