• 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

    尽然可以了。

  • 相关阅读:
    OpenStack安装及监控配置视频教程
    具有可视化的功能的一款开源软件Gource
    Ubuntu 12.04使用演示
    VisualRoute for Mac OS 体验
    P1006-传纸条
    Leetcode-1157 Online Majority Element In Subarray(子数组中占绝大多数的元素)
    Leetcode-1156 Swap For Maximum Repeated Substring(单字符重复子串的最大长度)
    Leetcode-1155 Number of Dice Rolls With Target Sum(掷骰子的N种方法)
    Leetcode-1154 Ordinal Number Of Date(一年中的第几天)
    P1508-Likecloud-吃、吃、吃
  • 原文地址:https://www.cnblogs.com/SamRichard/p/3974420.html
Copyright © 2020-2023  润新知