1、资料
下载地址
http://sourceforge.net/projects/gsoap2/
官网
http://genivia.com/Products/gsoap/index.html
官方学习教程
http://genivia.com/Products/gsoap/documentation.html
2、使用VS2010创建简单WebService
2.1 创建工程
New project --> Visual C# --> ASP.Net Empty Web Application
2.2 添加WebServices
Add New Item --> Web Service
2.3 WebService代码
修改了下原有代码,加法接口
namespace WebApplication_Test { /// <summary> /// Summary description for WebService1 /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. // [System.Web.Script.Services.ScriptService] public class WebService1 : System.Web.Services.WebService { [WebMethod] public double TestAdd(double a, double b) { return a + b; } } }
2.4 运行结果
http://localhost:12676/WebService1.asmx
作为服务器的链接地址
3 使用Gsoap生成代码
这里使用gsoap_2.8.17版本,最新的请到官网中下载。
用到.\gsoap-2.8\gsoap\bin\win32
wsdl2h.exe 根据WebService生成.h文件,其中描述了soap服务器的接口等,可以通过doxygen来获得头文件信息。
cmd窗口运行命令:
wsdl2h.exe -o head.h http://localhost:12676/WebService1.asmx?WSDL
-o 指定需要输出的头文件,默认为当前目录
head.h 为输出的.h文件
http://localhost:12676/WebService1.asmx?WSDL 为服务器地址+?WSDL
soapcpp2.exe 解析头文件,生成相应的源代码,运行:
soapcpp2.exe -C -i -x head.h -I ../../Import
常用命令
-C 仅生成客户端代码
-S 仅生成服务器端代码
-c 产生纯C代码,否则是C++代码(与头文件有关)
-I 指定import路径,导入../../Import(不导入会失败)
-x 不要产生XML示例文件
-i 生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)。
生成最终文件如下:
其中xxxProxy.h、xxxProxy.cpp即为客户端类代码
对于应用程序,需要使用到的为
soapC.cpp、soapH.h、soapStub.h、soapWebService1SoapProxy.cpp、soapWebService1SoapProxy.h、WebService1Soap.nsmap
以及 ../../stdsoap2.cpp、../../stdsoap2.h
4 生成客户端程序
4.1 简单的创建MFC对话框程序
4.2 添加以上soap文件
由于MFC默认要求CPP文件包含stdafx.h头文件,针对soapC.cpp、soapWebService1SoapProxy.cpp、stdsoap2.cpp,直接编译会提示
1>soap\soapC.cpp(16): warning C4627: '#include "soapH.h"': skipped when looking for precompiled header use 1> Add directive to 'StdAfx.h' or rebuild precompiled header 1>soap\soapC.cpp(2119): fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "StdAfx.h"' to your source? 1> soapWebService1SoapProxy.cpp 1>soap\soapWebService1SoapProxy.cpp(11): warning C4627: '#include "soapWebService1SoapProxy.h"': skipped when looking for precompiled header use 1> Add directive to 'StdAfx.h' or rebuild precompiled header 1>soap\soapWebService1SoapProxy.cpp(221): fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "StdAfx.h"' to your source? 1> stdsoap2.cpp 1>soap\stdsoap2.cpp(895): warning C4244: 'return' : conversion from 'std::streamsize' to 'size_t', possible loss of data
可手动修改添加头文件,或者修改编译条件
4.3 调用webService
响应OnOK程序,代码如下
#include "soapWebService1SoapProxy.h" #include "WebService1Soap.nsmap" void CTestSoapCPlusPlusDlg::OnBnClickedOk() { // TODO: Add your control notification handler code here //CDialogEx::OnOK(); WebService1SoapProxy mySoap; _ns1__TestAdd stuParam; stuParam.a = 10.0; stuParam.b = 100.0; _ns1__TestAddResponse stuResponse; //! 调用 char szSever[] = "http://localhost:12676/WebService1.asmx?wsdl"; if (SOAP_OK == mySoap.TestAdd(szSever, NULL, &stuParam, &stuResponse)) { CString strMsg; strMsg.Format("result:%.2f", stuResponse.TestAddResult); MessageBox(strMsg); } else { CString strMsg; strMsg.Format("result:%s", mySoap.soap_fault_string()); MessageBox(strMsg); } }
注意包含文件
soapWebService1SoapProxy.h,WebService1Soap.nsmap
其中:
szServer指定服务器,如果不明确指定,则使用默认服务器
OK,大功告成
5 碰到的问题
5.1 nafxcw.lib 同 LIBCMT.lib冲突
1> TestSoapDlg.cpp 1>nafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) already defined in LIBCMT.lib(new.obj) 1>nafxcw.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in LIBCMT.lib(delete.obj) 1>nafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new[](unsigned int)" (??_U@YAPAXI@Z) already defined in libcpmt.lib(newaop.obj) 1>nafxcw.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete[](void *)" (??_V@YAXPAX@Z) already defined in LIBCMT.lib(delete2.obj) 1>J:\C++\Soap\gSoap\Program\TestSoap\Release\TestSoap.exe : fatal error LNK1169: one or more multiply defined symbols found 1> 1>Build FAILED. 1> 1>Time Elapsed 00:00:06.67 ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
原因:
nafxcw是MFC运行链接库libcmt是C运行库,编译器先链接了libcmt,再链接nafxcw,导致符号重复定义,具体参见
http://support.microsoft.com/kb/148652/zh-cn
解决:
将两个库都忽略,再按顺序添加,编译器将根据指定的顺序执行链接
注意:
Debug版本下两个库为 nafxcwd.lib、LIBCMTD.lib
Release版本下两个库为 nafxcw.lib、LIBCMT.lib
不注意可能会出现很坑的错误。。。。
5.2 stdSoapC.cpp 无法解析的外部符号_namespace
/// Constructor with engine input+output mode control WebService1SoapProxy(soap_mode iomode);
SOAP_C_UTFSTRING
包括websevices、客户端、gsoap文件,见
http://download.csdn.net/detail/otosu/6953421