c++调用webservice接口的几种方法以及实例

c++调用webservice接口的几种方法以及实例

前言

最近在做这方面的工作,过程中遇到一些问题,故在此整理并分享一下,让后来者少走一些弯路.废话不多说,直接上干货.
准备工具:sproxy.exe/wsdl.exe;gsoap.均存在我的网盘中(还有一些其他好东西),大家自行伸手.(提取码:oJyA)

c++调用webservice的几种方法

目前,常用的调用方法有三种(个人知识有限,欢迎提点),本文中主要介绍第一和第三种方法:

  1. 使用sproxy.exe生成头文件,此种方法最简单,直接加载到项目中调用即可;
  2. 使用wsdl.exe生成头文件,加载到项目中调用,与第一点同理,但未尝试,有空再回来补充;
  3. 使用gsoap生成文件,把生成的相关文件均加载到项目中调用(此方法较第一点比较麻烦);

关于webservice的准备工作

首先你得有webservice地址,然后你才能够调用.
网上有很多公共的webservice接口,这里用其中一个"国内手机号码归属地查询WEB服务"来举个栗子.
一般的接口是这样的: http://www.webxml.com.cn/WebServices/MobileCodeWS.asmx

第一步,添加后缀

添加后缀 ?wsdl 得到如下网址:
http://www.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
打开是这样,说明成功
在这里插入图片描述

第二步,保存文件

把网页上的这些文件另存为wsdl格式的文件,右键->另存为即可下载.
在这里插入图片描述
下载完成.

方法一:使用sproxy.exe生成头文件并使用

1.生成头文件

sproxy使用方法: sproxy.exe /wsdl /out:“生成头文件目录名称” “生成的wsdl文件的路径”
eg:我的文件放在F:\webservice.WSDL转换成C转换成C++代码中,使用cmd进入此文件夹,并输入命令:

F:\webservice.WSDL转换成C转换成C++代码> .\sproxy.exe /wsdl /out:"F:\webservice.WSDL转换成C转换成C++代码\MobileCodeWS.h" "F:\webservice.WSDL转换成C转换成C++代码\MobileCodeWS.wsdl"
  • 1

执行完成后,会生成MobileCodeWS.h文件.
在这里插入图片描述

2.使用接口实例

观察一下生成的.h中要使用的接口:
在这里插入图片描述
有三个参数,最后一个参数是返回的结果.

1.首先添加头文件以及使用命名空间

    #include "MobileCodeWS.h"
    using namespace MobileCodeWS;
  • 1
  • 2

2.实例化

CMobileCodeWS *oMobileWS = new CMobileCodeWS;
  • 1

3调用以及传参

int iRet = oMobileWS->getMobileCodeInfo((CComBSTR)"15481348245",(CComBSTR)"",&bsRet);
  • 1

4转换

//BSTR转换方法使用_com_util::ConvertBSTRToString(bsRet)
  • 1

注意:

  • CComBSTR头文件:<comdef.h>
  • 使用_com_util::ConvertBSTRToString需添加#pragma comment(lib, “comsuppw.lib”)

方法二:使用wsdl.exe

这个方法可能适合c#使用,c++未尝试,待更.
使用方法类似方法一,自行研究.

方法三:使用gsoap.exe生成文件

由于未知原因,在使用第一种方法时,第一步生成头文件就失败,无法解析wadl的内容,报error.因此本人在网上搜罗大牛的博客查询资料借鉴整理验证,集前人所得才可最终成功.此方法稍微复杂一点点点点,各位看官请耐心.

1.使用wsdl2生成头文件

注意:
如果说传输的内容中含有中文,则需要增加一个bat文件,把传输类型由std::string转为wchar_t*,由宽字符传输,则可以解决乱码问题.刚开始由于没有添加处理文件导致后续接收到的中文乱码,折腾了半天,希望大家少走弯路.
bat文件(用txt文本保存如下文件,再修改后缀为bat即可)中一句话:

xsd__string = | std::wstring | wchar_t*

在gsoap-2.8\gsoap\bin\win32目录下,首先使用wsdl2.exe生成头文件:

F:\gsoap-2.8\gsoap\bin\win32> .\wsdl2h.exe -o .\MobileCodeWS.h .\MobileCodeWS.wsdl
或者不生成wsdl文件,直接使用wsdl的网址也可以生成
F:\gsoap-2.8\gsoap\bin\win32> .\wsdl2h.exe -o .\MobileCodeWS.h http://www.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
添加bat项:
F:\gsoap-2.8\gsoap\bin\win32> .\wsdl2h.exe -o .\MobileCodeWS.h .\MobileCodeWS.wsdl -t chinano1.bat
  • 1
  • 2
  • 3
  • 4
  • 5

2.使用soapcpp2生成系列文件

 PS F:\gsoap-2.8\gsoap\bin\win32> .\soapcpp2.exe -C .\MobileCodeWS.h -I F:\gsoap-2.8\gsoap\import -x
  • 1

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

在这里插入图片描述
执行成功后会生成红框中的文件
在这里插入图片描述

3.使用实例

1.加载入项目中
把上图红框中的五个文件(除了soapClientLib.cpp),以及gsoap下的stdsoap2.h和stdsoap2.cpp两个文件添加到项目中.
在项目中添加这七个文件后,cpp文件需要修改属性:在项目中的cpp上右键属性,选择不使用预编译头.
在这里插入图片描述
2.调用流程
首先需要添加头文件:
#include “soapH.h”
#include “MobileCodeWSSoap.nsmap”

实例如下:

#include "stdafx.h"
#include <iostream>
#include "soapH.h"
#include "MobileCodeWSSoap.nsmap"
#include <fstream>
using namespace std;

int main () 
{  
	// SOAP的客户端
	struct soap m_oSoap;
	// WebService调用对象
	class _ns1__getMobileCodeInfo getMobileCodeObject;
	// WebService返回对象
	class _ns1__getMobileCodeInfoResponse getMobileCodeResponseObject;
	// SOAP初始化
	soap_init(&m_oSoap);
	// 调用函数的参数赋值
	char strName[24] = {0};
	sprintf(strName,"15742451354");
	wchar_t *wstrName = A2W(strName);
	getMobileCodeObject.mobileCode = wstrName;
/*如果生成头文件时没有修改类型,那么用如下方式赋值,接收的类型当然也是string:
std::string strName = "15742451354";
getMobileCodeObject.mobileCode = strName;
*/

	// 发送WebService请求,并获得返回结果
	int nResult = soap_call___ns1__getMobileCodeInfo(&m_oSoap,NULL,NULL,&getMobileCodeObject,getMobileCodeResponseObject);
	// 操作成功
	if(SOAP_OK == nResult)
	{
		// 输出返回结果
		wchar_t* strResult = getMobileCodeResponseObject.getMobileCodeInfoResult;
		wcout.imbue(locale("chs"));
		wcout<<"wcout:"<<strResult<<endl;
	}
	/// 关闭SOAP
	soap_destroy(&m_oSoap);
	soap_end(&m_oSoap);
	soap_done(&m_oSoap);

	system("pause");
}  
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
/*====================================================================================================== =======================================================================================================*/ /*======================================================================================================== 如何使用? 1.引入DLL文件,引入头本文件,就已声明了导入函数 //要引入DLL的方法 //1、把SERIALPORTDLL1.dll和SERIALPORTDLL1.lib拷贝到工程目录下 //2、然后在 工程->设置->连接->分类->常规->对象/库模块输入:SERIALPORTDLL1.lib 2.调用Init初始化串口 3.调用SetReceiveFuntion(&ReveveChar);指定接收和处理数据的函数 4.实现void ReveveChar(WPARAM data, LPARAM port)这个函数 5.调用SendData发送数据 6.ClosePort(); ========================================================================================================*/ /*======================================================================================================= 函 数 名: Init 功 能: 打开并初始化串口 参数说明: UINT port //端口号 UINT baud //波特率 char parity = 'N' //校验位,默认为无校验位 UINT databits = 8 //数据位,一个字节的位数,默认为8位 UINT stopbit = 1 //停止位,默认为1位 使用例子: Init(2,9600); //打开串口2,波特率9600,其它值为默认值(无奇偶校验、数据位为8、停止位为1) Init(4,4800,'N',10);//打开串口4,波特率为4800,无奇偶校验,数据位为10,(停止位默认为1) ... ... ======================================================================================================*/ extern "C" __declspec(dllimport) void Init( UINT port, //端口号 UINT baud, //波特率 char parity = 'N', //校验位 UINT databits=8 , //数据位 UINT stopbit=1 //停止位 ); /*========================================================================================================== 函 数 名: SendData 功 能: 向串口发送数据,使用之前必须先调用Init函数初始化串口 参数说明: char data[] //要发送的数据 int datalen //发送数据的长度 使用例子: 例1: char a[] = {0x01,0x03,0x00,0x03,0x00,0x02,0x34,0x0B};//准备要发送的十六进制:01 03 00 03 00 02 34 0B SendData(a,8); //向串口发送十六进制数:01 03 00 03 00 02 34 0B 例2: char a[] = "$01001000020110*" //准备要发送的字符串$01001000020110* SendData(a,16); //向串口发送:$01001000020110* ============================================================================================================*/ extern "C" __declspec(dllimport) void SendData( char data[], int datalen ); /*=================================================================================================================== 函 数 名: SetReceiveFuntion 功 能: 指定接收数据的函数,指定好后,串口接收缓冲区每有一个字节的数据时会自动触发和调用所指定的函数 参数说明: a、参数需要一个函数指针, b、该指针指向一个用于接收数据的函数(该函数由用户自己声明、定义和实现), c、用户定义该函数时必须要满足一下条件: 1、该函数为全局函数 2、返回值为void 3、形参为两个,类型为:形参为UINT,LONG 使用例子: 1、void ReveveChar(WPARAM data, LPARAM port);//声明一个用于接收数据的全局函数,本头文件已默认声明这个函数,用户无需再次声明 2、 CString strTemp; void ReveveChar(WPARAM data, LPARAM port)//实现这个接收数据并处理数据的函数 { static int RecevCount = 0; //用于接收字节数的计数 char str[512] = ""; sprintf(str,"%02x",data); //接收十六进制数,并格式化为字符形式 strTemp += str; RecevCount++; if (RecevCount >= 8) //接收到数据长度等于了协议长度,则开始进行协议的处理 { RecevCount = 0; strTemp = "接收到得数据协议为" + strTemp; AfxMessageBox(strTemp); strTemp = ""; } } 3、SetReceiveFuntion(&ReveveChar);//指定void ReveveChar(WPARAM data, LPARAM port);该函数接收和处理数据 =========================================================================================================================*/ extern "C" __declspec(dllimport) void SetReceiveFuntion(void (*pfCallBack)(WPARAM data, LPARAM port)); /*================================================= 函 数 名: ClosePort 功 能: 关闭由Init函数打开的串口 参数说明: 无需参数 调用例子: ClosePort(); =================================================*/ extern "C" __declspec(dllimport) void ClosePort(); /*=============================================================================================================== 函 数 名: ReveveChar 功 能: 每当串口接收到一个字符(字节)时就会自动触发和调用这个函数, 用户只需实现不必也不能去亲自调用, 注意:打开串口后,必须要调用SetReceiveFuntion(ReveveChar) 参数说明: data //接收到的是串口中的一个字节数据 port //端口号,表明是哪个端口接收到的数据 调用例子: 只要实现,无需自己调用。 实现处理数据可参考如下简单的例子,思想是边接收数据边处理 void ReveveChar(WPARAM data, LPARAM port) { static int RecevCount = 0; //用于接收字节数的计数 char str[512] = ""; sprintf(str,"%02x",data); //接收十六进制数,并格式化为字符形式 strTemp += str; RecevCount++; if (RecevCount >= 8) //接收到数据长度等于了协议长度,则开始进行协议的处理 { RecevCount = 0; strTemp = "接收到得数据协议为" + strTemp; AfxMessageBox(strTemp); strTemp = ""; } } 说明:本函数并非为导出函数,写在这里仅仅是起到声明一个函数的作用,用户也可以删除掉,自己声明和实现! ===============================================================================================================*/ void ReveveChar(WPARAM data, LPARAM port);

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值