Reputation: 31
I'm trying to create a web service in C++ using gSOAP. I generated a couple of headers from ONVIF wsdl:
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
After that I compiled the headers generating C++ service proxies and objects:
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
in order to obtain an application similar to the one described by gSOAP documentation: http://www.cs.fsu.edu/~engelen/soapdoc2.html#tth_sEc7.2.8
Compiling in Visual Studio, i get the following errors:
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
I tried to follow what the documentation says (http://www.cs.fsu.edu/~engelen/soapdoc2.html#tth_sEc19.35) about the serializers not being compiled at all because of the definition WITH_NOGLOBAL and compiled an empty env.h file, but that didn't solve the problem.
I searched the web but I can't find any solution. The problem seems related not to the Header and Fault themselves but the the pointers. Right? What should I do?
Upvotes: 3
Views: 3093
Reputation: 1708
Here is the solution.
wsdl2h -x -Nan -o an.h http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl
. Note that I'm using option -Nan
here to let soapcpp2 generate two service/proxy classes for the two services defined by the two bindings in this WSDL. Otherwise you get one service/proxy class that combines the two together in one class, which is not elegant (but works either way).wsdl2h -x -o dm.h http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl
env.h
env.h
and add #import "xop.h"
and #import "wsa5.h"
. Basically, you want all plugin-based headers to be imported here, since the plugins must work with global (non-C++-namespaced) structures. Also, the env.h
file can be customized by adding a struct SOAP_ENV__Header
and/or a struct SOAP_ENV__Detail
structure. This is needed to exchange SOAP Headers and specific SOAP Fault details. In this case that won't be needed, since #import "wsa5.h"
defines our SOAP Headers already for WS-Addressing.soapcpp2 -penv env.h
to generate the global SOAP Header and SOAP Fault serialization code (envStub.h
, envH.h
and envC.cpp
).an.h
and add the following definitions for SOAP Header and Faultsan.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
change the line struct SOAP_ENV__Envelope { struct SOAP_ENV__Header_ *SOAP_ENV__Header; _XML SOAP_ENV__Body; };
by using struct SOAP_ENV__Header_
instead of struct SOAP_ENV__Header
.an.h
change line struct SOAP_ENV__Fault_* Fault
by using struct SOAP_ENV__Fault_
instead of struct SOAP_ENV__Fault
.dm.h
.soapcpp2 -j -x -qAn -I $GSOAPPATH/gsoap/import -I $GSOAPPATH/gsoap an.h
to generate C++ service and proxy classes in the An
namespace (with option -qAn
).soapcpp2 -j -S -x -qDm -I $GSOAPPATH/gsoap/import -I $GSOAPPATH/gsoap dm.h
.duration
plugin (this custom serializer is optional, edit typemap.dat
to remove it if desired and then rerun wsdl2h), copy $GSOAPPATH/custom/duration.c
to local duration.cpp
(note the .cpp extension, since MSVC++ does not like mixing .c with .cpp sources).duration.cpp
and change #include "soapH.h"
to #include "anH.h"
.c++ yourclientapp.cpp DmC.cpp AnC.cpp envC.cpp DmDeviceBindingProxy.cpp AnRuleEngineBindingProxy.cpp AnAnalyticsEngineBindingProxy.cpp stdsoap2.cpp dom.cpp duration.cpp
or server-side c++ yourserviceapp.cpp DmC.cpp AnC.cpp envC.cpp DmDeviceBindingService.cpp AnRuleEngineBindingService.cpp AnAnalyticsEngineBindingService.cpp stdsoap2.cpp dom.cpp duration.cpp
.$GSOAPPATH/gsoap/plugin/wsaapi.c
with your code (but rename wsaapi.c
to wsaapi.cpp
since MSVC++ does not like mixing .c with .cpp sources).EDIT
You can skip steps 6-8 if you change typemap.dat
as follows, then rerun wsdl2h with the modified typemap.dat
:
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_
Upvotes: 2
Reputation: 101
I faced this issue and almost lost my mind trying to find the solution. I noticed that a directive using #ifndef WITH_NOIDREF
encapsulates some of soap_(out|in)_PointerToSOAP_ENV__(Fault|Header)
indentifiers. Then when compile with the WITH_NOIDREF
defined the erros messages decreases a little. So I manually encapsulates all the soap_(out|in)_PointerToSOAP_ENV__(Fault|Header)
identifiers and it worked!
Example:
#ifndef WITH_NOIDREF
/// The soap_(out|in)_PointerToSOAP_ENV__(Fault|Header) indentifiers
// ...
#endif //WITH_NOIDREF
I'm afraid you are using windows, but I made some scripts to automate the whole process in:
https://github.com/yudi-matsuzake/onvif-mkmakefile
Upvotes: 0
Reputation: 11963
The code generated using the -q
option seems to have a namespace problem with soap_in_PointerToSOAP_ENV__Fault
and soap_in_PointerToSOAP_ENV__Header
. The same problem occurs also with only 1 wsdl.
An other approach is to use the -p
option like this :
soapcpp2.exe -j -S dm.h -IC:\gsoap-2.8\gsoap\import;C:\gsoap-2.8\gsoap -x -pDm
soapcpp2.exe -j -S an.h -IC:\gsoap-2.8\gsoap\import;C:\gsoap-2.8\gsoap -x -pAn
Upvotes: 0