windows7下php扩展调用动态链接库dll

本人是php的菜鸟(入门都还不算,c++也才入门),很多说的不对的地方请多多包涵。

因为涉及到要用php调用c++的动态链接库,所以在网上搜了很多资料。

最初海量的搜了很多,第一种方法是做成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,选择从网络安装

windows7下php扩展调用动态链接库dll_第1张图片

默认c盘,可改

windows7下php扩展调用动态链接库dll_第2张图片

下载缓存随意,安装结束记得删掉,我是放在桌面的

windows7下php扩展调用动态链接库dll_第3张图片windows7下php扩展调用动态链接库dll_第4张图片

在中国,就选http://mirrors.163.com,后面一直下一步到结束。

windows7下php扩展调用动态链接库dll_第5张图片

    下载完成后,搜索并勾选gcc-coregcc-g++makegdbbinutils,以上所有项目都在 devel 文件夹下。选择完毕后会显示你选择的安装包,再下一步开始安装直至安装结束。

二、骨架搭建:

1.配置php环境变量

path中添加php环境目录,例如下图

windows7下php扩展调用动态链接库dll_第6张图片

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,进入源码包extE:\php-5.6.25\ext,输入php.exe  ext_skel_win32.php--extname=test,这里test代表你的php扩展名,得到如图效果,扩展骨架创建成功

windows7下php扩展调用动态链接库dll_第7张图片

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.

恭喜!你的骨架搭建成功啦!

三、调用C++动态库

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)//传入参数赋值,这里的lint类型,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; }

你可能感兴趣的:(php,php,php扩展,动态链接库,dll)