我正在尝试使用 gSOAP 在 C++ 中创建 Web 服务。 我从 ONVIF wsdl 生成了几个 header :
wsdl2h -x -o dm.h http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl -tC:\gsoap-2.8\gsoap\typemap.dat
wsdl2h -x -o an.h http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl -tC:\gsoap-2.8\gsoap\typemap.dat
之后,我编译了生成 C++ 服务代理和对象的 header :
soapcpp2.exe -j -S dm.h -IC:\gsoap-2.8\gsoap\import;C:\gsoap-2.8\gsoap -x -qDm
soapcpp2.exe -j -S an.h -IC:\gsoap-2.8\gsoap\import;C:\gsoap-2.8\gsoap -x -qAn
为了获得类似于 gSOAP 文档中描述的应用程序:http://www.cs.fsu.edu/~engelen/soapdoc2.html#tth_sEc7.2.8
在 Visual Studio 中编译,出现以下错误:
error C3861: 'soap_in_PointerToSOAP_ENV__Fault': identifier not found
error C3861: 'soap_in_PointerToSOAP_ENV__Header': identifier not found
error C3861: 'soap_out_PointerToSOAP_ENV__Fault': identifier not found
error C3861: 'soap_out_PointerToSOAP_ENV__Header': identifier not found
我试图按照文档中所说的 ( http://www.cs.fsu.edu/~engelen/soapdoc2.html#tth_sEc19.35 ) 关于序列化器由于定义 WITH_NOGLOBAL 而根本没有被编译的内容并编译了一个空的 env.h 文件,但这并没有解决问题。
我在网上搜索过,但找不到任何解决方案。问题似乎与 Header 和 Fault 本身无关,而与指针有关。正确的? 我该怎么办?
最佳答案
这是解决方案。
- 运行
wsdl2h -x -Nan -o an.h http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl
。请注意,我在这里使用选项-Nan
让 soapcpp2 为这个 WSDL 中的两个绑定(bind)定义的两个服务生成两个服务/代理类。否则你会得到一个服务/代理类,将两者结合在一个类中,这并不优雅(但无论哪种方式都有效)。 - 运行
wsdl2h -x -o dm.h http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl
- 新建文件
env.h
- 编辑
env.h
并添加#import "xop.h"
和#import "wsa5.h"
。基本上,您希望在此处导入所有基于插件的 header ,因为插件必须使用全局(非 C++ 命名空间)结构。此外,可以通过添加struct SOAP_ENV__Header
和/或struct SOAP_ENV__Detail
结构来自定义env.h
文件。这是交换 SOAP header 和特定 SOAP 错误详细信息所必需的。在这种情况下,不需要这样做,因为#import "wsa5.h"
已经为 WS-Addressing 定义了我们的 SOAP header 。 - 运行
soapcpp2 -penv env.h
生成全局SOAP Header和SOAP Fault序列化代码(envStub.h
,envH.h
和envC.cpp
)。 - 编辑
an.h
并为 SOAP Header 和 Fault 添加以下定义
an.h:
struct SOAP_ENV__Header_
{
// place SOAP Header elements here, if any
};
struct SOAP_ENV__Fault_
{
char *faultcode;
char *faultstring;
char *faultactor;
struct SOAP_ENV__Detail_ *detail;
struct SOAP_ENV__Code_ *SOAP_ENV__Code;
struct SOAP_ENV__Reason_ *SOAP_ENV__Reason;
char *SOAP_ENV__Node;
char *SOAP_ENV__Role;
struct SOAP_ENV__Detail_ *SOAP_ENV__Detail;
};
struct SOAP_ENV__Detail_
{
char *__any;
int __type;
void *fault;
};
struct SOAP_ENV__Code_
{
char *SOAP_ENV__Value;
struct SOAP_ENV__Code_ *SOAP_ENV__Subcode_;
};
struct SOAP_ENV__Reason_
{
char *SOAP_ENV__Text;
};
- 在
an.h
中更改行struct SOAP_ENV__Envelope { struct SOAP_ENV__Header_ *SOAP_ENV__Header; _XML SOAP_ENV__正文; };
通过使用struct SOAP_ENV__Header_
而不是struct SOAP_ENV__Header
。 - 在
an.h
中,通过使用struct SOAP_ENV__Fault_
而不是struct SOAP_ENV__Fault
更改行struct SOAP_ENV__Fault_* Fault
。 - 对
dm.h
重复步骤 6-8。 - 现在您可以使用 C++ 命名空间,因此运行
soapcpp2 -j -x -qAn -I $GSOAPPATH/gsoap/import -I $GSOAPPATH/gsoap an.h
生成 C++ 服务和代理类在An
命名空间中(使用选项-qAn
)。 - 运行
soapcpp2 -j -S -x -qDm -I $GSOAPPATH/gsoap/import -I $GSOAPPATH/gsoap dm.h
。 - 由于我们使用的是
duration
插件(此自定义序列化程序是可选的,如果需要,请编辑typemap.dat
将其删除,然后重新运行 wsdl2h),复制$GSOAPPATH/custom/duration.c
到本地duration.cpp
(注意 .cpp 扩展名,因为 MSVC++ 不喜欢将 .c 与 .cpp 源混合)。 - 编辑
duration.cpp
并将#include "soapH.h"
更改为#include "anH.h"
。 - 然后用你的代码编译整个东西,例如客户端
c++ yourclientapp.cpp DmC.cpp AnC.cpp envC.cpp DmDeviceBindingProxy.cpp AnRuleEngineBindingProxy.cpp AnAnalyticsEngineBindingProxy.cpp stdsoap2.cpp dom.cpp duration.cpp
或服务器端c++ yourserviceapp .cpp DmC.cpp AnC.cpp envC.cpp DmDeviceBindingService.cpp AnRuleEngineBindingService.cpp AnAnalyticsEngineBindingService.cpp stdsoap2.cpp dom.cpp duration.cpp
. - 如果您使用的是 WS-Addressing 插件,还要用您的代码编译
$GSOAPPATH/gsoap/plugin/wsaapi.c
(但将wsaapi.c
重命名为wsaapi.cpp
因为 MSVC++ 不喜欢将 .c 与 .cpp 源混合使用)。
编辑
如果按如下方式更改 typemap.dat
,则可以跳过步骤 6-8,然后使用修改后的 typemap.dat
重新运行 wsdl2h:
SOAP_ENV__Envelope = struct SOAP_ENV__Envelope { struct SOAP_ENV__Header_ *SOAP_ENV__Header; _XML SOAP_ENV__Body; }; | struct SOAP_ENV__Envelope
SOAP_ENV__Header = struct SOAP_ENV__Header_ { /* place SOAP Header elements here, if any */ }; | struct SOAP_ENV__Header_
SOAP_ENV__Fault = \
struct SOAP_ENV__Fault_\
{\
char *faultcode;\
char *faultstring;\
char *faultactor;\
struct SOAP_ENV__Detail_ *detail;\
struct SOAP_ENV__Code_ *SOAP_ENV__Code;\
struct SOAP_ENV__Reason_ *SOAP_ENV__Reason;\
char *SOAP_ENV__Node;\
char *SOAP_ENV__Role;\
struct SOAP_ENV__Detail_ *SOAP_ENV__Detail;\
};\
struct SOAP_ENV__Detail_\
{\
char *__any;\
int __type;\
void *fault;\
};\
struct SOAP_ENV__Code_\
{\
char *SOAP_ENV__Value;\
struct SOAP_ENV__Code_ *SOAP_ENV__Subcode_;\
};\
struct SOAP_ENV__Reason_\
{\
char *SOAP_ENV__Text;\
};\
| struct SOAP_ENV__Fault_
关于c++ - 具有来自 ONVIF 规范的多个 wsdl 的 gSOAP 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28718193/