如何使用gSOAP将web服务转换成C++代码

来源:互联网 发布:陆金所 数据建模工程师 编辑:程序博客网 时间:2024/05/17 01:43
问题1:怎样使用gSOAP生成代码
将gSOAP下载下来之后有2个exe文件:

----------------------第一步-----------------------------
wsdl2h.exe是根据web服务的地址或者wsdl文件生成头文件的(之后的cpp文件都是基于的生成的这个头文件),命令是:
wsdl2h -o alldevices.h-t typemap.dathttp://218.62.42.51:8088/MonitorWS/webservice/cameraws?wsdl http://218.62.42.51:8088/MonitorWS/webservice/centers?wsdl http://218.62.42.51:8088/MonitorWS/webservice/dvrinfows?wsdl
其中多个地址只需要以空格分隔就ok,执行命令以后,就会生成alldevices.h文件。
当需要处理中文的时候,需要加上标红的这段,typemap.dat可以修改提供的文件,也可以自己写下面的这1句,然后保存即可。
xsd__string = | std::wstring | wchar_t*
wsdl的相关参数如下:
命令解释:
wsdl2h -o 头文件名 WSDL文件名或URL
wsdl2h常用选项
-o 文件名,指定输出头文件 
-n 名空间前缀 代替默认的ns 
-c 产生纯C代码,否则是C++代码 
-s 不要使用STL代码 
-t 文件名,指定type map文件,默认为typemap.dat 
-e 禁止为enum成员加上名空间前缀 
----------------------第二步-----------------------------
使用soapcpp2.exe工具生成框架中的.h和.cpp文件
在执行命令之前,需要在同目录下复制过来以下文件,不然会报错

命令为:
soapcpp2 -i -C -x alldevices.h
soapcpp2常用选项:
-C 仅生成客户端代码 
-S 仅生成服务器端代码 
-L 不要产生soapClientLib.c和soapServerLib.c文件 
-c 产生纯C代码,否则是C++代码(与头文件有关) 
-I 指定import路径(视自己的解压包目录而定);
-x 不要产生XML示例文件 
-i 生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)。
在这里还需要将新预编译头去掉,如下:

工程采用Unicode字符集:

----------------------第三步-----------------------------
导入项目,在VC里新建项目,找到项目所在文件夹,将生成的soapC.cpp,soapH.h,soapStub.h,XXXWebServiceSoapProxy.cpp,XXXWebServiceSoapProxy.h,XXX.nsmap以及gSOAP系统文件stdsoap2.cpp和stdsoap2.h文件复制到该项目文件夹,同时加载到工程中。

问题2:代码怎样初始化
最终目的是调用web服务提供的函数,但是在此之前还有2个步骤:
1. 创建SOAP对象
cameraWSImplSoapBindingProxy camera;
//其中“cameraWSImplSoapBindingProxy ”是继承自SOAP类的。
2. 创建SOAP参数以及结果对象
ns1__GetProvinceCameras getprovincecamerap;//参数对象
ns1__GetProvinceCamerasResponse getprovincecamerar;//结果对象
getprovincecamerap有很多参数,需要对它们进行赋值,例如:
getprovincecamerap.arg0 = lic;
每一个调用的函数都会有这2个参数,例如:
function(getprovincecamerap,getprovincecamerar),调用函数得出的结果就存于getprovincecamerar中了。
问题3:json解析
对于有些web服务得出的结果是字符串还好,有些web服务得出的结果的格式是json的,这就需要解析json。
可以直接使用现有工具jsoncpp实现解析。
Step1:从网址https://github.com/open-source-parsers/jsoncpp下载jsoncpp文件夹,编译得到静态lib库文件,将其拷到项目文件夹下。
Step2:在代码中写上
#pragma comment(lib,"./lib/json_vc71_libmt.lib")//lib路径自行修改即可调用。
Step3:解析:
string cc = UnicodeToANSI(allcameras);//将获取到的内容转成string类型
Json::Reader reader; //定义读取器
Json::Value root;//根元素
if (!reader.parse(cc, root, false)) //进行解析,成功返回0
{
return -1;
}
int size = root.size();
std::list<Camera *> mycamera;
for (int i=0; i<size; ++i)
{
Camera * Ctemp = new Camera;
Ctemp->cameraId = root[i]["cameraId"].asInt();//使用root操作json对象

细节编程问题
1. list使用
std::list<Type*> mycamera;//定义某种类型的链表
可以调用很多函数,比如:mycamera.push_back(Ctemp);
读取链表需要定义迭代器:
list<Prodevice *>::iterator ite;
for(ite = myprodev.begin();ite != myprodev.end(); ite++)
{
string id = (*ite)->institutionId;
......各种操作
2. 文件读写
最后需要把获取到的所有摄像头信息存到文件里去,使用的是<fstream>头文件。
ofstream outfile; //定义文件处理对象
outfile.open("camerasinfo.txt");//打开文件
outfile<<"局站ID:"<<id<<" 摄像头个数:"<<subsum<<endl;//写入文件

附:重要转换函数
----------------------char * 转 wchar_t *-----------------------------
wchar_t* c2w(char *str)
{
int length = strlen(str)+1;
wchar_t *t = (wchar_t*)malloc(sizeof(wchar_t)*length);
memset(t,0,length*sizeof(wchar_t));
MultiByteToWideChar(CP_ACP,0,str,strlen(str),t,length);
return t;
}
-----------------------Unicode转ANSI---------------------------------
string UnicodeToANSI(const wstring& str)
{
char* pElementText;
int iTextLen;
// wide char to multi char
iTextLen = WideCharToMultiByte( CP_ACP,
0,str.c_str(),-1,NULL,
0,NULL,NULL );
pElementText = new char[iTextLen + 1];
memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
::WideCharToMultiByte( CP_ACP,
0,str.c_str(),-1,pElementText,
iTextLen,NULL,NULL );
string strText;
strText = pElementText;
delete[] pElementText;
return strText;
}