VC使用GSOAP调用C#WCF服务

首先声明:文章中的内容大都来源于网络,做的过程遇到了不少问题,所以想写下此文,记录一个完整的过程,以飨后人。

gSOAP是一个夸平台的,用于开发Web Service服务端和客户端的工具,在WindowsLinuxMAC OSUNIX下使用CC++语言编码,集合了SSL功能。

下载地址:http://sourceforge.net/projects/gsoap2

官方网站:http://genivia.com/Products/gsoap/index.html

1、配置gSOAP
下载gSOAP,解压后在gsoap\bin\win32里找到wsdl2h.exe和soapcpp2.exe程序。通过这两个程序可以生成客户端需要的C/C++文件。这两个程序的使用方法:
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放到soapcpp2.exe目录下,否则运行失败)
-C 仅生成客户端代码 
-S 仅生成服务器端代码 
-L 不要产生soapClientLib.c和soapServerLib.c文件 
-c 产生纯C代码,否则是C++代码(与头文件有关) 
-I 指定import路径(见上文) 
-x 不要产生XML示例文件 
-i 生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)

wsdl2h -s -t D:\gsoap-2.8\gsoap\typemap.dat  -o service1.h   http://192.168.20.251:8080/Service1.svc?wsdl

soapcpp2   -C -I D:\gsoap-2.8\gsoap\import service1.h -L -i -x

2、创建VC工程,把生成的文件拷到工程目录

“\gsoap-2.8\gsoap”目录下找到 stdsoap2.cpp 和stdsoap2.h 也复制到工程中去;设置新加的所有.cpp文件不要使用预编译头。

3、调用Web服务:

#include "stdafx.h"

#include "soapH.h"

#include "soapClientServiceSoapBindingProxy.h"

#include "ClientServiceSoapBinding.nsmp"

int _tmain(int argc,_TCHAR* argv[])

{

const char* server="http://XXXXX:81/Service1.svc"; 

BasicHttpBinding_USCOREIService1Proxy ss(server,SOAP_C_UTFSTRING);
double aa=10;
double bb =20;
_tempuri__add tempuri__add; 
tempuri__add.a=&aa;
tempuri__add.b =&bb;
_tempuri__addResponse tempuri__addResponse ;
if (ss.add(&tempuri__add,&tempuri__addResponse)==SOAP_OK)
{
double cc=*tempuri__addResponse.addResult;
ss.destroy();
return 0 ;
}
if (ss.error)
{
ss.soap_stream_fault(std::cerr);
ss.destroy();
return 0 ;
}
}


4、解决415错误:

 这个是由于服务端客户端soap协议不统一造成的,我使用的gsoap是2.8.8版本,编译出来的xxx.nsmap中soap协议是1.2版本,连接的wcf服务是1.1版本。

目前这个问题有两个方法可以解决,1,手工修改nsmap文件中的协议,2,使用gsoap编译器“-1”编译选项(此方法未测试,据说有些时候也无效)

//手动修改namespace, 生成soap1.1.
   struct  Namespace namespaces[] =
  {
   { "SOAP-ENV" , "http://schemas.xmlsoap.org/soap/envelope/" , NULL, NULL},
   { "SOAP-ENC" , "http://schemas.xmlsoap.org/soap/encoding/" , NULL, NULL},
   { "xsi" , "http://www.w3.org/2001/XMLSchema-instance" , NULL, NULL},
   { "xsd" , "http://www.w3.org/2001/XMLSchema" , NULL, NULL},
  
   
   //{"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", NULL},
   //{"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema", NULL},
   
   { "ns3" , "http://schemas.microsoft.com/2003/10/Serialization/" , NULL, NULL},
   { "ns1" , "http://tempuri.org/" , NULL, NULL},
   {NULL, NULL, NULL, NULL}
  };

5、解决中午乱码的问题:

通过上面的步骤,已经可以成功连接了,但是在遇到中文字符的时候,问题就出现了。

5.1中文字符返回值

这个解决的办法主要就是要把字符转换成utf-8

1>设置GSOAP的编码模式 soap_set_mode(soap, SOAP_C_UTFSTRING);

2>将传输回来的字符流进行字符转换

//ns5__SimpleNetObject是WCF中定义的结构体,返回值是此类型<br>  //mapServiceResponse用来接收返回值,参看前面的addResponse就明白了
ns5__SimpleNetObject d = *mapServiceResponse.PublishMapServiceResult;
std::wstring str;
std::string stt = d.Message;
//转换为utf-8编码
bool  fl = WFromUTF8( reinterpret_cast < const  char * >(stt.c_str()), str);
CString s = str.c_str();

3>字符转换函数

#if !defined(TEXTCONVERT_H)
#define TEXTCONVERT_H
//多字节字符串转换为宽字节字符串
// CodePage:[in]编码
// lpcwszText:[in]多字节字符串
// lppszVal:[out]宽字节字符串
//返回值:TRUE表示成功,其它表示失败
inline  BOOL  WcharFromChar( UINT  CodePage, const  char  *lpcszText,std::wstring &wstrVal)
{
     WCHAR  *lpwszVal( NULL );
     int  nLength(0); size_t  dwSize(0);
     nLength = ::MultiByteToWideChar( CodePage, 0, lpcszText, -1 , NULL, 0);
     if ( nLength <= 0 ) return  FALSE;dwSize = nLength * sizeof ( WCHAR );
     lpwszVal = ( WCHAR  *) malloc ( dwSize );
     if ( NULL == lpwszVal ) return  FALSE;
     memset (lpwszVal,0x0,dwSize);
     nLength = ::MultiByteToWideChar( CodePage, 0, lpcszText, -1 , lpwszVal, nLength ); 
     if ( nLength <= 0 )
     {
         free (lpwszVal);
         lpwszVal = NULL;
         return  FALSE;
     }
     wstrVal.assign( lpwszVal );
     free (lpwszVal);
     lpwszVal = NULL;
     return  TRUE;
}
 
//UTF-8字符串转换为宽字节字符串
// lpcwszText:[in]UTF-8字符串
// lppszVal:[out]宽字节字符串
//返回值:TRUE表示成功,其它表示失败
inline  BOOL  WFromUTF8( const  char  *lpcszText,std::wstring &wstrVal )
{
     return  WcharFromChar(CP_UTF8,lpcszText,wstrVal);
}
#endif

5.2中文字符参数

中文字符返回值的问题解决了,新的问题又出现了,如果按照上面的设置,如果是有中文字符的参数,这个参数就会乱码了,真是一波刚平一波又起啊。

有人提出了用setloacal的方法来解决,不过这个办法我使用的时候无效。

返回值乱码,我们是将其从转换成utf-8的编码方式,那么,我们传人的参数有问题,在传人参数之前,先将其转换成utf-8是不是就可以呢。(当前是unicode,大概等价于utf-16,未查证)

如果是linux系统,貌似有直接的装换函数,可惜我是在windows平台,那就自己写吧,有了上面的转换方法,照猫画虎,也就是那样。

//字符编码转换
std::string Convert(std::wstring str, int  targetCodepage)
{
     BYTE * pTargetData = NULL; 
     size_t  souceLen=WideCharToMultiByte(targetCodepage,0,( LPWSTR )str.c_str(),-1,( char  *)pTargetData,0,NULL,NULL); 
     pTargetData= new  BYTE [souceLen+1]; 
     memset (pTargetData,0,souceLen+1); 
     WideCharToMultiByte(targetCodepage,0,( LPWSTR )str.c_str(),-1, 
         ( char *)pTargetData,souceLen,NULL,NULL);
 
     std::string rt(( char *)pTargetData); 
     delete  [] pTargetData;
     return  rt; 
}

调用方法

CString str = _T("测试中文");

std::wstring ss = str;

std::string  var  =Convert(ss,CP_UTF8);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用gSOAP生成Onvif服务端,你需要按照以下步骤操作: 1. 下载和安装gSOAP:首先,你需要从gSOAP官方网站(https://www.genivia.com/downloads.html)下载并安装gSOAP工具包。根据你的操作系统选择合适的版本,并按照官方文档进行安装步骤。 2. 定义服务接口:使用gSOAP的接口定义语言(IDL)来定义你的Onvif服务接口。在IDL文件中,你可以定义服务的方法、参数和返回类型等。确保按照Onvif规范来定义你的服务接口。 3. 生成代码:使用gSOAP提供的工具来生成C/C++代码。你需要使用命令行工具 `soapcpp2` 并提供IDL文件作为输入。执行命令后,gSOAP将生成相应的服务端和客户端代码文件。 4. 实现服务逻辑:根据生成的代码,你需要实现Onvif服务的具体逻辑。这包括处理接收到的请求、执行相应的操作并构建响应。 5. 编译和构建:编译你的服务端代码,并链接所需的库文件。确保按照gSOAP文档提供的指导进行编译和构建步骤。 6. 运行服务端:运行生成的服务端程序,并确保它能够监听和处理来自客户端的请求。 请注意,这只是一个概述性的步骤,具体的实施可能因个人需求和环境而异。在实际开发中,你还需要了解Onvif协议规范和gSOAP工具的详细用法,并根据实际情况进行适当的配置和定制。 希望这些信息对你有所帮助!如果你有进一步的问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值