php 5.x 扩展开发要点
导语:php 5.x 扩展开发要点,最近因项目需要开发了一个windows dll形式的php扩展,实现访问soap webservice。下面就由小编为大家介绍一下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语言认识上要避免10大误区
PHP是一种非常流行的开源服务器端脚本语言,你在万维网看到的大多数网站都是使用php开发的。但是,你大概很奇怪的注意到有少部分的人发誓要离php远远的。但是令人更奇怪的是或者很震惊的说他们不用php并不是因为一些被证实的语言缺点。他们决定不用php,是因为误解...
-
php计算两个文件相对路径的方法
文章主要介绍了php计算两个文件相对路径的方法,涉及php操作字符串的`技巧,具有一定参考借鉴价值,需要的朋友可以参考下.一、问题:写一个php函数算出两个文件的相对路径。例如$a="/a/b/c/d/";$b="/a/b/12/34/",B相对于A的相对路径是什么?二、解决方法:?123456789101...
-
PHP数据类型之数组变量详解
导语:PHP是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。下面我们来看看PHP数据类型之数组变量详解,希望对大家有所帮助。PHP中的数组实际上是一个有序图,是一种把values映射到keys的类型。一个数组实际上就...
-
提高PHP执行效率的50个技巧
PHP是一种HTML内嵌式的语言,是一种在服务器端执行的嵌入HTML文档的脚本语言,下面是小编为大家整理的提高PHP执行效率的50个技巧,欢迎参考~1、用单引号代替双引号来包含字符串,这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会,注意:只有echo...