c++ - 具有来自 ONVIF 规范的多个 wsdl 的 gSOAP 服务器

标签 c++ web-services wsdl gsoap onvif

我正在尝试使用 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 本身无关,而与指针有关。正确的? 我该怎么办?

最佳答案

这是解决方案。

  1. 运行 wsdl2h -x -Nan -o an.h http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl。请注意,我在这里使用选项 -Nan 让 soapcpp2 为这个 WSDL 中的两个绑定(bind)定义的两个服务生成两个服务/代理类。否则你会得到一个服务/代理类,将两者结合在一个类中,这并不优雅(但无论哪种方式都有效)。
  2. 运行 wsdl2h -x -o dm.h http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl
  3. 新建文件env.h
  4. 编辑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 。
  5. 运行soapcpp2 -penv env.h生成全局SOAP Header和SOAP Fault序列化代码(envStub.h, envH.henvC.cpp)。
  6. 编辑 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;
};
  1. an.h 中更改行 struct SOAP_ENV__Envelope { struct SOAP_ENV__Header_ *SOAP_ENV__Header; _XML SOAP_ENV__正文; }; 通过使用 struct SOAP_ENV__Header_ 而不是 struct SOAP_ENV__Header
  2. an.h 中,通过使用 struct SOAP_ENV__Fault_ 而不是 struct SOAP_ENV__Fault 更改行 struct SOAP_ENV__Fault_* Fault
  3. dm.h 重复步骤 6-8。
  4. 现在您可以使用 C++ 命名空间,因此运行 soapcpp2 -j -x -qAn -I $GSOAPPATH/gsoap/import -I $GSOAPPATH/gsoap an.h 生成 C++ 服务和代理类在 An 命名空间中(使用选项 -qAn)。
  5. 运行 soapcpp2 -j -S -x -qDm -I $GSOAPPATH/gsoap/import -I $GSOAPPATH/gsoap dm.h
  6. 由于我们使用的是 duration 插件(此自定义序列化程序是可选的,如果需要,请编辑 typemap.dat 将其删除,然后重新运行 wsdl2h),复制 $GSOAPPATH/custom/duration.c 到本地 duration.cpp(注意 .cpp 扩展名,因为 MSVC++ 不喜欢将 .c 与 .cpp 源混合)。
  7. 编辑 duration.cpp 并将 #include "soapH.h" 更改为 #include "anH.h"
  8. 然后用你的代码编译整个东西,例如客户端 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.
  9. 如果您使用的是 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/

相关文章:

c++ - android studio 中的外部 C++ 源文件?

c++ - OS X 上 C++ 中的 sleep 操作

c++ - CMFCColorButton 上的颜色更改通知?

java - 为第三方创建/公开 Web 服务的设计决策

.net - 如何使 WSDL.exe 不生成 XxxAsync 方法(我仍然想要 Begin/EndXxx)

java - SOAP 和 Spring

c++ - 查找长度大于 10,000 的字符串的子序列

.net - 如何确定 .Net DLL 是否用于 GUI 应用程序或 Web 服务?

web-services - HTTP 406 和 415 错误代码

c# - 从 C# 中的 SOAP API 捕获实际错误详细信息