[原]C++ Soap客户端实例

解压gSoap2.8
通过WSDL文档,生成C/C++头文件
执行
gsoap-2.8/gsoap/bin/linux386/wsdl2h -o soapPHP.h Service.wsdl
拷贝gSOAP源代码中import文件夹下的stlvector.h文件到TestHeader.h同一目录,如果在解析WSDL文档时使用了-s参数,即不使用STL,则不需要拷贝这一文件。
gsoap-2.8/gsoap/bin/linux386/soapcpp2 -c soapPHP.h 
如:soapcpp2 -i -x -C -L calc.h
这一步将会得到几个. nsmap、.h和.cpp文件,如:calc.nsmap、soapC.cpp、soapH.h、soapStub.h、soapcalcProxy.cpp、soapcalcProxy.h
该步的目的:生成相应的底层通信代码。
----------------------------------------------------------------------
1 通过wsdl文件生成.h文件
从WSDL中产生头文件
用法:
wsdl2h -o 头文件名 WSDL文件名或URL
wsdl2h常用选项
-o 文件名,指定输出头文件
-n 名空间前缀 代替默认的ns
-c 产生纯C代码,否则是C++代码
-s 不要使用STL代码
-t 文件名,指定type map文件,默认为typemap.dat
-e 禁止为enum成员加上名空间前缀
type map文件用于指定SOAP/XML中的类型与C/C++之间的转换规则,比如在wsmap.dat里写
 
2 由.h文件生成所需要的cpp/c文件
用法
soapcpp2 头文件
例:
soapcpp2 ayandy.h
将生成下面这些文件
soapStub.h    // soap的存根文件,定义了ayandy.h里对应的远程调用模型
soapC.c soapH.h  // soap的序列和反序列代码,它已经包含了soapStub.h,服务器端与客户端都要包含它
soapClient.c soapClientLib.c // 客户端代码,soapClientLib.c文件则只是简单地包含soapClient.c和soapC.c
soapServer.c soapServerLib.c // 服务器端代码,soapServerLib.c文件则只是简单地包含soapServer.c和soapC.c
ServiceSoap.nsmap ServiceSoap12.nsmap // 名空间定义,服务器端与客户端都要包含它
soapServiceSoapProxy.h soapServiceSoap12Proxy.h // 客户端的C++简单包装(如果头文件是纯C代码,这两个文件就不会生成)
综上所述
如果编写服务器端,项目里应该加入soapServerLib.c,代码里包含头文件soapH.h
如果编写客户端,项目里应该加入soapClientLib.c,代码里包含头文件SoapH.h(或xxxxProxy.h)
当然,还要加入gsoap库里的stdsoap2.cpp文件(如果是写C代码,则加入stdsoap2.c)
如果看到soapcpp2提示:”Critical error: #import: Cannot open file "stlvector.h" for reading.“, 那是因为我们的头文件使用了STL(wsdl2h 没用-s选项),这时要使用-I选项指定gSOAP的 import文件路径,这个路径是"$gsoap\gsoap\import":
soapcpp2 ayandy.h -I D:\gsoap-2.7\gsoap\import
soapcpp2常用选项
-C 仅生成客户端代码
-S 仅生成服务器端代码
-L 不要产生soapClientLib.c和soapServerLib.c文件
-c 产生纯C代码,否则是C++代码(与头文件有关)
-I 指定import路径(见上文)
-x 不要产生XML示例文件
-i 生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)。
实例
PHP服务端
<?
class Service {
public function runServer($a, $b) {
return $a.$b." KKK";
}
}
$server = new SoapServer('Service.wsdl');
$server->setClass("Service"); //注册Service类的所有方法
$server->handle(); //处理请求
?>
c++客户端
#include <iostream>
#include "soap/ServicesBinding.nsmap"
#include "soap/soapServicesBindingProxy.h"
using namespace std;
void soapclient()
{
    //加载ServicesBinding.nsmap和soapServicesBindingProxy.h文件
    ServicesBindingProxy serviceBinding;
    char *iResult;
    if (serviceBinding.runServer(NULL,NULL,"i'am","Rooney",iResult)  == SOAP_OK){
        cout <<iResult <<endl;
    }
    else{
        cout << "yes" << endl;
    }
    return;
}
int main()
{
    soapclient();
    return 0;
}
//解决C++调用php中文件乱码问题
***Proxy.cpp的调用接口内添加
soap_set_mode(soap, SOAP_C_UTFSTRING);
如:
int ServicesBindingProxy::runServer(const char *endpoint, const char *soap_action, char *a, char *b, char *&runServer)
{ struct soap *soap = this;
struct ns1__runServer soap_tmp_ns1__runServer;
struct ns1__runServerResponse *soap_tmp_ns1__runServerResponse;
if (endpoint)
soap_endpoint = endpoint;
if (!soap_endpoint)
soap_endpoint = "http://localhost/Services.php";
if (!soap_action)
soap_action = "urn:Services#Service#runServer";
soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
soap_tmp_ns1__runServer.a = a;
soap_tmp_ns1__runServer.b = b;
soap_begin(soap);
soap_serializeheader(soap);
soap_serialize_ns1__runServer(soap, &soap_tmp_ns1__runServer);
soap_set_mode(soap, SOAP_C_UTFSTRING);//新增语句-----------
if (soap_begin_count(soap))
return soap->error;
if (soap->mode & SOAP_IO_LENGTH)
{ if (soap_envelope_begin_out(soap)
...
...
}
原文地址:https://www.cnblogs.com/rooney/p/2583656.html