C++调用WebService

1. gSOAP是一个开源的项目,用它可以方便的使用c/c++地进行SOAP客户端和服务器端编程,而不必了解xml和SOAP协议的细节

wsdl2h.exe: 编译wsdl文件生成c/c++头文件

-o 文件名,指定输出头文件 
-n 名空间前缀 代替默认的ns 
-c 产生纯C代码,否则是C++代码 
-s 不要使用STL代码 
-t 文件名,指定type map文件,默认为typemap.dat 
-e 禁止为enum成员加上名空间前缀

soapcpp2.exe: gSOAP编译器,编译头文件生成服务器和客户端都需要的c/c++文件(默认使用STL,需要stlvector.h)

-C 仅生成客户端代码 
-S 仅生成服务器端代码 
-L 不要产生soapClientLib.c和soapServerLib.c文件 
-c 产生纯C代码,否则是C++代码(与头文件有关) 
-I 指定import路径(见上文) 
-x 不要产生XML示例文件 
-i 生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)

2. 生成存客户端存根程序和框架
wsdl2h -o xx.h http://192.168.40.8:88/GMM?wsdl 

或者 wsdl2h -o xx.h http://js.gps163.com:8994/Server/CsService.svc?wsdl
soapcpp2 -C -L -x -i xx.h (soapcpp2 xx.h -C -I D:gsoap-2.7gsoapimport)

3. 把如下生成的文件添加到项目:
soapStub.h,soapH.h,stdsoap2.h

soapC.cpp,soapClient.cpp,stdsoap2.cpp

soapBasicHttpBinding_USCOREIGMMProxy.cpp

soapBasicHttpBinding_USCOREIGMMProxy.cpp

BasicHttpBinding_USCOREIGMM.nsmap

wsock32.lib

4. 调用

#include "soapBasicHttpBinding_USCOREIGMMProxy.h"
#include "BasicHttpBinding_USCOREIGMM.nsmap"

//代理方式调用不需要初始化
//struct soap xxSoap;
//soap_init(&xxSoap);

//代理类对象
xxWebServiceSoap xxProxy; 

//设置头信息
//SOAP_ENV__Header envHeader;
//xxProxy.soap->header = &envHeader;

//web服务对象
_ns1__xx xx; 

//web服务结果对象 
_ns1__xxResponse xxResponse;

//调用WebService方法


5. 使用的例子:

 1 CString CGetLocation::GetLocation(int iLon, int iLat)
 2 {
 3     CString strAddress = _T("");
 4 
 5     struct soap soap1 ;
 6     soap_init(&soap1);
 7     soap_set_mode(&soap1, SOAP_C_MBSTRING);
 8 
 9     BasicHttpBinding_USCOREIGMMProxy locationService(soap1);
10 
11     _ns3__GetLocation    getLocation;
12     _ns3__GetLocationResponse getLocationRes;
13 
14     bool blOffset = false;
15     getLocation.Latitude = &iLat;
16     getLocation.Longitude = &iLon;
17     getLocation.blOffset = &blOffset;
18 
19     int nOK = -1;
20 
21     try
22     {
23         nOK = locationService.GetLocation(strWCFUrl.c_str(), NULL, &getLocation, &getLocationRes);
24     }
25     catch (...)
26     {
27         CString strLog;
28         strLog.Format(_T("GetLocation try catch error : %d
"), GetLastError());
29         TRACE(strLog);
30         return strAddress;
31     }
32 
33 
34     if (nOK != SOAP_OK)
35     {
36         char szError[255] = {0};
37         soap_sprint_fault(&soap1, szError, 255);
38 
39         CString strLog;
40         strLog.Format(_T("SOAP Error: %s
"), szError);
41         TRACE(strLog);
42         return strAddress;
43     }
44 
45     if (getLocationRes.GetLocationResult == NULL || (*getLocationRes.GetLocationResult).empty())
46     {
47         CString strLog;
48         strLog.Format(_T("SOAP Result: Error
"));
49         TRACE(strLog);
50         return strAddress;
51     }
52 
53     strAddress = (*getLocationRes.GetLocationResult).c_str();
54     return strAddress;
55 }

// 2015.09.15

延伸:C++ 用gSOAP 实现面向Java 开发的 WebService 时,会出现中文乱码问题;

这是由于java和gsoap的C++程序对字符串的处理并不一致,Java默认是UTF-8编码,而C++是ASCII编码。

为解决此问题,一个比较好的方法是在gsoap生成的C++代码中用wchar_t*代替char*,这需要在运行wsdl2h生成gSOAPInterface.h文件时指定必要的类型映射,这可以利用wsdl2h命令的-t选项来实现。

1)从gsoap的安装目录(例如我的是C:gsoap-2.8)中找到gsoap子目录,可以在其中看到一个typemap.dat文件,

这是缺省的类型映射文件

2)将该文件拷贝到当前目录,并更名为mytypemap.dat

3)用任意的文本编辑器打开该文件,添加以下代码:

xsd__string = | wchar_t* | wchar_t*

4 )保存更改后的文件,执行解析命令;

举例:

wsdl2h.exe -t mytypemap.dat -o gSOAPInterface.h http://59.50.104.87:8080/LBS-Environmental/lbsService?wsdl

可以看到,新生成的gSOAPInterface.h 文件中,字符串的声明变成了wchar_t*。

5 ) 根据前面的方法执行 soapcpp2.exe;

举例:

soapcpp2.exe gSOAPInterface.h -C -L -x -i -I ....import

这样字符串处理之后,字符串以 wchar_t* 的方式传入就OK了。

当然在初始化的时候要加入以下代码:

1      struct soap *soapclient1 = soap_new();
2         soap_init(soapclient1);
3         soapclient1->recv_timeout = 10;
4         soapclient1->send_timeout = 10;
5         soapclient1->connect_timeout = 10;
6         soap_set_mode(soapclient1, SOAP_C_UTFSTRING);
7     soapclient = (int *)soapclient1;
8    
GoSoapClient = (int *)new ILbsServiceHttpBindingProxy();

结束加入:

1    soap_destroy((soap *)soapclient);
2     soap_end((soap *)soapclient);
3     soap_done((soap *)soapclient);
4     delete soapclient;
5     delete GoSoapClient;

//2015.10.10

今天又遇到中文乱码的问题。

根据上面的方法还是不行。

so 又进行了调试。

解决方案跟上面类似,但用上面的方法不行的原因是。

之前解析出来的字符串类型是 

可以用mytypemap 替换掉。

今天是  

所以今天采用手动替换, 

在解析的 gSOAPInterface.h 中, 有中文的string 全部换成wchar_t *。

然后执行 soapcpp2.exe gSOAPInterface.h -C -L -x -i -I ....import

尽然可以了。

原文地址:https://www.cnblogs.com/SamRichard/p/3974420.html