最初海量的搜了很多,第一种方法是做成com组件调用,但是要调用的是普通的dll,所以失败。
而后有看到一篇调用非com组件的,通过dynwrap.dll调用,但是一直试不出来,如今回头看可能是版本和位数的问题,应该也是可行的。
最后一种就是php扩展了,最初搜索的方向可能有些不对,导致搜索到的总不是我想要的,此时可以询问一下其他人,说不定会给你新的思路。最终做出来啦还是很开心的,很有成就感的
文档说明、实例及php5.6.25源码包
Ø 下载安装VS(如VS2010)
Ø 搭建php环境(自行搭建和集成环境皆可,如wampserver,最好下载x86,我用的wampserver3.0.6)
Ø 下载php环境对应版本的源码包(一定要对应,我这里下载php 5.6.25,wampserver中集成的可能有多版本,选择一个即可)
Ø 下载安装Cygwin(为了在Windows环境下模拟Linux环境)
进入官网下载安装包,安装Cygwin,选择从网络安装
默认c盘,可改
下载缓存随意,安装结束记得删掉,我是放在桌面的
在中国,就选http://mirrors.163.com,后面一直下一步到结束。
下载完成后,搜索并勾选gcc-core、gcc-g++、make、gdb、binutils,以上所有项目都在 devel 文件夹下。选择完毕后会显示你选择的安装包,再下一步开始安装直至安装结束。
1.配置php环境变量
在path中添加php环境目录,例如下图
Cmd进入命令模式,输入php –v,出现下图画面即为成功
2.将下载的php5.6.25源码包解压,例如解压到E:\php-5.6.25。
进入解压的源码包目录下ext(如E:\php-5.6.25\ext),打开该目录下的ext_skel_win32.php
找到$cygwin_path = 'c:\cygwin\bin';将路径改成cygwin的安装目录
3.运行cmd,进入源码包ext,E:\php-5.6.25\ext,输入php.exe ext_skel_win32.php--extname=test,这里test代表你的php扩展名,得到如图效果,扩展骨架创建成功
4. 打开目录E:\php-5.6.25\ext,就会看到test文件夹,这就是你的扩展。
打开php环境下dev目录E:\wamp\bin\php\php5.6.25\dev,将二进制包php5ts.lib拷到你的test目录下。
进入E:\php-5.6.25\win32\build,将config.w32.h.in复制到E:\php-5.6.25\main目录下,并删掉后缀.in,再编辑更名后的config.w32.h,添加一行代码:
#define PHP_COMPILER_ID "VC11" //(这里的VC11根据你的phpinfo中Compiler填写,我这是MSVC11(Visual C++ 2012),所以填VC11)
用vs打开E:\php-5.6.25\ext\test下的test.dsp,转换,选择Release_TS,(win32和x64根据phpinfo中Architecture的值选择)生成。生成的dll在E:\php-5.6.25\Release_TS目录下。
5.将生成的dll ,php_test.dll拷到E:\wamp\bin\php\php5.6.25\ext目录下,并更改E:\wamp\bin\php\php5.6.25目录下的php.ini文件,添加extension=phptest.dll。
重启wampserver(重启你的php,若有warning有可能是你的源码与环境版本不对应,一定要同一版本,且位数相同)。
创建php文件,内容:
echo confirm_test_compiled (“123”)
?>
运行输出:
Congratulations!You have successfully modified ext/test/config.m4. Module 123 is now compiledinto PHP.
恭喜!你的骨架搭建成功啦!
1.用VS打开之前生成的骨架项目,E:\php-5.6.25\ext\test\test.sln。
将GB.dll和GB.lib(你的动态库)拷到E:\php-5.6.25\ext\test目录下。
在php_test.h中加入代码:
#ifdef _DEBUG
#pragma comment(lib , "GB.lib")
#else
#pragma comment(lib , "GB.lib")
#endif
#define GB_API extern "C"__declspec(dllimport)
2.然后找到test.c文件中PHP_FUNCTION(confirm_test_compiled)函数(自动生成的测试函数,可以删除掉),在后面添加:
PHP_FUNCTION(Initialization_GB)
{
//头文件里面引入动态库后可以直接调用动态库里的函数,不需要声明,以下代码可以参照自己的函数写
int m_type;//表枚举值
char *m_ip;//服务器IP
int m_ip_len;
int m_port;//端口
unsigned long hanlde;//句柄
int count;//记录数
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lsl",&m_type,&m_ip,&m_ip_len,&m_port) == FAILURE)//传入参数赋值,这里的l指int类型,s指字符串,一共三个参数
{
RETURN_NULL();
}
php_printf("m_type= %u",m_type);
php_printf(" ");
PHPWRITE(m_ip,m_ip_len);
php_printf("\n m_port = %u",m_port);
php_printf("!\n");
//调用GB动态链接库方法,Initialization,获取句柄值
hanlde =Initialization(m_type,m_ip,m_port);
//输出句柄值
php_printf("port = %u",hanlde);
}
3. test.c文件中找到constzend_function_entry test_functions[] = {
在PHP_FE(confirm_test_compiled, NULL)下面添加代码:
PHP_FE(Initialization_GB, NULL)
4.选择Release_TS和win32(与之前生成时相同),生成成功。将生成的php_test.dll文件拷到E:\wamp\bin\php\php5.6.25\ext下,将之前的dll替换掉。
5.将GB.dll拷到C:\Windows\System32目录下(64位拷到C:\Windows\SysWOW64),重启php
在test.php中添加代码:echoInitialization_GB(6,"192.168.0.50",4000);
运行,页面显示如下:
初始化成功!
至此调用动态库的一个简单例子就完成了。
1.版本问题
源码版本和环境版本一定要相同,位数也要注意相同(建议选择32位)
2. 如果遇到2019连接错误,那么通常是没有删除预处理定义中的宏LIBZEND_EXPORTS
遇到什么问题可以评论一起讨论,一起进步~
前面的例子中我用了php_printf();和PHPWRITE();前一个跟c中的printf差不多,php中使用会直接输出,还有就是用返回值。
不过涉及到中文之后,因为编码不一样会出现乱码。我的解决方法是使用mb_convert_encoding($str, "UTF-8", "GBK")对传出的字符串进行转换,若参数传入可以将"UTF-8"和"GBK"交换,亲测有用。
返回值宏定义(在Zend/zend_API.h中):
#define RETVAL_RESOURCE(l) ZVAL_RESOURCE(return_value, l)
#define RETVAL_BOOL(b) ZVAL_BOOL(return_value, b)
#define RETVAL_NULL() ZVAL_NULL(return_value)
#define RETVAL_LONG(l) ZVAL_LONG(return_value, l)
#define RETVAL_DOUBLE(d) ZVAL_DOUBLE(return_value, d)
#define RETVAL_STRING(s, duplicate) ZVAL_STRING(return_value, s, duplicate)
#define RETVAL_STRINGL(s, l, duplicate) ZVAL_STRINGL(return_value, s, l, duplicate)
#define RETVAL_EMPTY_STRING() ZVAL_EMPTY_STRING(return_value)
#define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor)
#define RETVAL_FALSE ZVAL_BOOL(return_value, 0)
#define RETVAL_TRUE ZVAL_BOOL(return_value, 1)
#define RETURN_RESOURCE(l) { RETVAL_RESOURCE(l); return; }
#define RETURN_BOOL(b) { RETVAL_BOOL(b); return; }
#define RETURN_NULL() { RETVAL_NULL(); return;}
#define RETURN_LONG(l) { RETVAL_LONG(l); return; }
#define RETURN_DOUBLE(d) { RETVAL_DOUBLE(d); return; }
#define RETURN_STRING(s, duplicate) { RETVAL_STRING(s, duplicate); return; }
#define RETURN_STRINGL(s, l, duplicate) { RETVAL_STRINGL(s, l, duplicate); return; }
#define RETURN_EMPTY_STRING() { RETVAL_EMPTY_STRING(); return; }
#define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
#define RETURN_FALSE { RETVAL_FALSE; return; }
#define RETURN_TRUE { RETVAL_TRUE; return; }