BACK TO MAIN PAGE

gSOAP FAQ

Where can I find a good description of the mod_gsoap module to get it running?
Visit All things mod_gsoap.
How do I increase the speed of XML messaging and serialization?
The default settings are choosen to maximize portability and compatibility. The settings can be tweaked to optimize the performance as follows:
  • Tweak the buffer size SOAP_BUFLEN by changing the SOAP_BUFLEN macro in stdsoap2.h (and compile your project with stdsoap2.c/.cpp, DO NOT USE libgsoap with the old buffer size). Test with buffer sizes 32768, 65536, 131072 for example.
  • Use HTTP keep-alive SOAP_IO_KEEPALIVE at the client-side when the client needs to make a series of calls to the same server. Server-side keep-alive support can greatly improve performance of both client and server. But be aware that clients and services under Unix/Linux require signal handlers to catch dropped connections.
  • Use HTTP chunked transfer SOAP_IO_CHUNKED.
  • Do NOT use gzip compression, since the overhead of compression is typically higher than the bandwidth gains.
  • Set the SOAP_XML_TREE flag to disable id-ref multi-ref object (de)serialization. This boosts performance significantly and works with SOAP document/literal style (i.e. no id-ref graph serialization). This flag is NOT compatible with SOAP encoded style that requires id-ref object serialization.
  • Compile stdsoap2.c/.cpp with -DWITH_NOIDREF to improve performance by permanently disabling id-ref multi-ref object (de)serialization. Again, this is NOT compatible with SOAP encoded style that requires id-ref object serialization.
  • Do NOT use DEBUG mode, since the overhead of logging is significant.
I cannot deserialize polymorphic objects in my C-based service, but in C++ it works fine?
Services developed in C++ with gSOAP support full polymorphism, including xsd:anyType. However, the C language limitations make it more difficult to map schema complexType extensions to the limited C types. In order to support polymorphism in C, we suggest to use advanced features such as the int __type; void* construct to serialize a pointer to an object of type X. This is done in your application code by setting __type = SOAP_TYPE_X and the void* pointer to the object (see documentation). Obviously, the deserializer automatially sets __type and void* according to the XML content and its xsi:type value which is required. When xsi:type values are not provided, such as for the base case of an XSD extension/restriction, you should match the content according to the element tag name by defining a type (struct or typedef) with the element name. See documentation Section "Customizing Data Bindings With The typemap.dat File". Use the typemap.dat file for wsdl2h to automatically replace all occurences of a polymorphic type.
I get a "No deserializer found to deserialize a '...' using encoding style 'http://schemas.xmlsoap.org/soap/encoding/'" error from an Axis server. What is the problem?
Some toolkits, including Axis, require typed SOAP RPC messages with xsi:type information for each accessor. Use soapcpp2 option -t to automatically re-generate serialization code to produce typed messages.
I suspect that gSOAP has a memory leak, because no memory is released when I check the malloc() behavior. Am I correct?
The gSOAP engine uses a memory management method to allocate and deallocate memory. The deallocation is performed with soap_destroy() followed by soap_end(). However, when you compile with -DDEBUG or -DSOAP_MEM_DEBUG then no memory is released until soap_done() is invoked. This ensures that the gSOAP engine can track all malloced data to verify leaks and double frees in debug mode. Use -DSOAP_DEBUG to use the normal debugging facilities without memory debugging. Note that some compilers have DEBUG enabled in the debug configuration, so this behavior should be expected unless you compile in release config.
What is the "Data corruption in dynamic allocation" error?
When your application uses soap_malloc() to allocate a (temporary) chunk of data and the allocated size is exceeded, the gSOAP engine will detect this buffer overrun in DEBUG mode. Check your code and/or enlarge the allocated buffer.
The C/C++ compiler I'm using produces an error for empty structs and/or classes that are present in the generated code. What should I do?
Use -DWITH_NOEMPTYSTRUCT as a C/C++ compiler option to add dummy members automatically to the generated code (gSOAP version 2.7.9g or higher). I downloaded a new release version to upgrade. However, I got a link error for one of more function calls in the code generated by soapcpp2.
You were probably using the platform-independent release earlier and upgraded with a platform-dependent release. The platform-independent release builds libgsoap, while the platform-dependent release assumes you will link stdsoap2.c/pp. Thus, you're using the old gSOAP engine with new code generated by soapcpp2.
How do I build gSOAP on HP-UX?
  1. Install GNU m4: http://www.gnu.org/software/m4/
  2. Install flex from: http://flex.sourceforge.net/ We only need the command-line tool 'flex' and 'libfl.a' which we got at this stage. Make sure the libfl.a is installed on a library path accessible to cc.
  3. If HTTP compression is required, then install zlib: http://www.zlib.net/ Make sure libz is installed on a library path accessible to cc.
  4. If HTTPS and SSL for WS-Security are required, then install OpenSSL.
  5. When OpenSSL is NOT installed in the above steps, execute in the root dir of the gsoap package:
    $ ./configure --disable-openssl
    
    otherwise execute:
    $ ./configure
    
  6. Edit config.h:
    	set HAVE_REALLOC 1
    	comment out:
    	/* #define realloc rpl_realloc */
    
    Also make sure that in config.h:
    #define HAVE_STRTOLL 0
    #define HAVE_STRTOULL 0
    
    Then execute:
    $ make
    
    There will be errors when building the tests, but ignore these
  7. Edit the Makefile to make sure that:
    LEXLIB = /usr/local/lib/libfl.a
    
    and rebuild:
    $ make
    
  8. If there is a problem building wsdl2h, do this:
    cd ../wsdl
    
    Edit Makefile:
    wsdl2h_DEPENDENCIES = wsdlC.cpp $(top_builddir)/gsoap/stdsoap2.cpp
    AM_LDFLAGS = $(INCLUDES) -DWITH_OPENSSL -L$(srcdir)
    SOAP_CCP_LIB_SSL = $(top_builddir)/gsoap/stdsoap2.cpp
    
    and execute:
    $ make
    $ cd ../..
    $ make install-exec
    
    now we have soapcpp2 and wsdl2h installed
  9. Then execute:
    $ make install
    
  10. If all else fails, you can build the soapcpp2 and wsdl2h tools using the supplied MakefileManual files in the source directories. Before doing so, remove the old package and unpack again to start fresh. Then:
    cd gsoap/src; make -f MakefileManual
    cd gsoap/wsdl; make -f MakefileManual
    
    In your projects use gsoap/stdsoap2.h and gsoap/stdsoap2.c (or gsoap/stdsoap2.cpp) directly instead of the libgsoap library (which is built from stdsoap2.c/.cpp). If stdsoap2.c/.cpp do not compile, modify stdsoap2.h for portability. For example, if socklen_t is not defined, change it to an int as in:
    #elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN)
    || defined(FREEBSD) || defined(__FreeBSD__) || defined(OPENBSD) ||
    defined(__QNX__) || defined(QNX) || defined(OS390) || defined(HP_UX)# define
    SOAP_SOCKLEN_T socklen_t
    
    To:
    #elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN)
    || defined(FREEBSD) || defined(__FreeBSD__) || defined(OPENBSD) ||
    defined(__QNX__) || defined(QNX) || defined(OS390) || defined(HP_UX)# define
    SOAP_SOCKLEN_T int
    
I get macro redefinition errors on my Windows platform, what should I do?
When you get macro redefinitions, such as
warning C4005: 'AF_IPX' : macro redefinition
then try arrange your include list such that <windows.h> is included after "stdsoap2.h". Or define _WINSOCKAPI_ first:
#define _WINSOCKAPI_ // stops windows.h including winsock.h
#include <windows.h>
...
#include "soapH.h" // also includes "stdsoap2.h"
The stdsoap2.h code includes winsock2.h, which clashes with winsock.h included by windows.h. Similar problems may occur when stdafx.h is included.

If all else fails, revert back to older winsock.h by changing in stdsoap2.h:

#include <winsock.h> // was: <winsock2.h>
How do I build a universal PPC/Intel binary for MAC OS?
To build a Mac OS X Universal Binary you have to run "automake --ignore-deps":
automake --ignore-deps && ./configure CFLAGS="-arch ppc -arch i386" LDFLAGS="-arch ppc -arch i386" && make clean && make
How do I build the libraries with libtool?
In configure.in change AC_PROG_RANLIB into AC_PROG_LIBTOOL. In gsoap/Makefile.am replace the .a and the _a respectively by .la and _la in this file, so that it looks like:
lib_LTLIBRARIES = libgsoap.la libgsoap++.la libgsoapck.la libgsoapck++.la libgsoapssl.la libgsoapssl++.la
libgsoap_la_SOURCES = stdsoap2.c
libgsoap_la_CFLAGS = $(SOAPCPP2_DEBUG) $(SOAPCPP2_NONAMESPACES) -D$(platform)
libgsoap___la_SOURCES = stdsoap2_cpp.cpp
libgsoap___la_CXXFLAGS = $(SOAPCPP2_DEBUG) $(SOAPCPP2_NONAMESPACES) -D$(platform)
libgsoapck_la_SOURCES = stdsoap2_ck.c
libgsoapck_la_CFLAGS = $(SOAPCPP2_DEBUG) $(SOAPCPP2_NONAMESPACES) -D$(platform) -DWITH_COOKIES
libgsoapck___la_SOURCES = stdsoap2_ck_cpp.cpp
libgsoapck___la_CXXFLAGS = $(SOAPCPP2_DEBUG) $(SOAPCPP2_NONAMESPACES) -D$(platform) -DWITH_COOKIES
libgsoapssl_la_SOURCES = stdsoap2_ssl.c
libgsoapssl_la_CFLAGS = $(SOAPCPP2_DEBUG) $(SOAPCPP2_NONAMESPACES) -D$(platform) -DWITH_OPENSSL -DWITH_DOM -DWITH_GZIP
libgsoapssl___la_SOURCES = stdsoap2_ssl_cpp.cpp
libgsoapssl___la_CXXFLAGS = $(SOAPCPP2_DEBUG) $(SOAPCPP2_NONAMESPACES) -D$(platform) -DWITH_OPENSSL -DWITH_DOM -DWITH_GZIP
After the modifications run
autoconf -f -i -v configure
make
make install
Is gSOAP portable to NonStop Tandem?
Yes. A software bridge for the engine to work on NonStop Tandem is included in the package. All generated code is platform-independents, so the soapcpp2/wsdl2h tools can be used on any platform to produce the client/server interface.
Why do I get a 'Compliance Warning'?
WS-I Basic Profile compliance warnings are meant to inform you about potential interoperability problems with other SOAP/XML Web services. The WS-I Basic Profile publication consists of a set of non-proprietary Web services specifications, along with clarifications and amendments to those specifications which promote interoperability. Compliance warnings for existing services should be ignored, because compliance requires changes to the service WSDL that would break other applications that depend on the service. You may consider these compliance issues for new services however, see the Basic Compliance Report we prepared for gSOAP.
What is the difference between qualified element/attribute forms and unqualified forms?
When a schema defines element forms to be qualified by default (elementFormDefault="qualified"), the header file includes a directive
//gsoap ns schema elementForm: qualified
Likewise, when the default is unqualified, you will find
//gsoap ns schema elementForm: unqualified
When an element form is qualified by default, elements in XML instances of the schema are required to be namespace qualified. Without going into too much detail, the XML basically looks like:
<x:foo xmlns:x="urn:foobar">
  <x:bar>bar is qualified</x:bar>
</x:foo>
or:
<foo xmlns="urn:foobar">
  <bar>bar is qualified</bar>
</foo>
When the element form is unqualified (as in SOAP RPC encoding), we would have:
<x:foo xmlns:x="urn:foobar">
  <bar>bar is unqualified</bar>
</x:foo>
Note that sometime we can have multiple namespaces as in:
<x:foo xmlns:x="urn:foo">
  <y:bar xmlns:y="urn:bar"></y:bar>
</x:foo>
or:
<x:foo xmlns:x="urn:foo" xmlns="urn:bar">
  <bar></bar>
</x:foo>
In the last example the bar element belongs to the "urn:bar" namespace, because the default namespace is "urn:bar". With Visual Studio .NET 2003 WSDL import, we could not successfully deserialize data from a multi-namespace situation when a response element contains an element of struct type in a second namespace. The individual members of the struct were ignored on the .NET side until the element form default 'qualified' was defined.
Tuning TCP/IP TIME_WAIT for systems with high connection rates
When a large number of connections in the TIME_WAIT state are observed, e.g. using the "netstat" command to monitor open TCP/IP connections, the system exhibits poor throughput possibly coupled with high CPU use or refusal to accept new connections by soap_accept().

The TIME_WAIT state is used to deal with possible problems related to unreliable or delayed packet delivery. TCP holds connections for a temporary waiting period (TIME_WAIT) to ensure that any delayed packets are caught and not treated as new connection requests. The size of TIME_WAIT is supposed to be twice the maximum segment lifetime or twice the time a packet can remain alive on a particular IP network. For some operating systems, this can be as high as 4 minutes. On busy systems, this can lead to a depleation of TCP port resources. Low throughput may occur due to many connections sitting in TIME_WAIT state.

Set the soap.accept_flags |= SO_LINGER and soap.linger_time = n with integer n before calling soap_accept(). This works on most systems, but zapping the TIME_WAIT state is not always encouraged!

If that does not work, then reduce the operating system setting for TIME_WAIT substantially to the operating system minimum of 15 or 30 seconds (depending on OS).

  1. For Windows: Use regedit and create a REG_DWORD named TcpTimedWaitDelay under
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TcpIp\Parameters
    
    Set it to a decimal value of 30 which is for 30 seconds - the minimum.
  2. For AIX: To see the current TCP_TIMEWAIT value, run the following command:
    /usr/sbin/no a | grep tcp_timewait 
    
    To set the TCP_TIMEWAIT values to 15 seconds, run the following command:
    /usr/sbin/no o tcp_timewait =1 
    
    The tcp_timewait option is used to configure how long connections are kept in the timewait state. It is given in 15-second intervals, and the default is 1.
  3. For Linux: Set the timeout_timewait paramater using the following command:
    /sbin/sysctl -w net.ipv4.vs.timeout_timewait=30 
    
    This will set TME_WAIT for 30 seconds.
  4. For Solaris: Set the tcp_time_wait_interval to 30000 milliseconds as follows:
    /usr/sbin/ndd -set /dev/tcp tcp_time_wait_interval 30000
    
Client receives ECONNRESET from a gSOAP server
Set the soap.linger SO_LINGER socket option in the server code using soap.accept_flags |= SO_LINGER before calling soap_accept(). This forces the server to block on the close attempt until it is able to transmit the data or until it decides it is unable to deliver the information after a timeout period. The soap.linger value controls the timout period (the linger time resolution is system-dependent, consult the setsockopt man page. However, according to some experts only zero and nonzero values matter).
Why do I get a warning on a parameter with 'a type that does not correspond to the required unique type'?
SOAP RPC literal encoding requires the operation parameters to be described as top-level Schema elements in WSDL. Therefore, a service operation with parameter 'x' of type 'X' has an <element name="x" type="X"/> definition in the Schema of the service. A parameter 'x' of type 'Y' cannot be defined, since 'x' is already bound to type 'X'. If you must use SOAP RPC literal encoding, rename the parameter, e.g. 'y' of type 'Y', or define new schema namespaces by qualifying the parameter names, e.g. 'arg__x', 'arg__y', etc. You can use document literal encoding to avoid this problem, or SOAP RPC encoding (not WS Basic Profile compliant).
I get a link error in Visual Studio C++. What should I do?
  • Visual Studio C++ differs from compilers such as GCC with respect to the C or C++ compilation mode based on file extensions, which means that:
  • For C++ builds: change .c into .cpp extensions.
  • For C++ builds: do not use soapcpp2 option -c.
  • For C++ builds: link your application with soapC.cpp, soapClient.cpp (or soapServer.cpp for services), and stdsoap2.cpp.
  • Check the actual-formal parameter passing (soapStub.h contains the prototypes of the generated stub functions).
  • You need winsock.dll ("wsock32.lib"). To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link" tab (the project file needs to be selected in the file view) and add "wsock32.lib" to the "Object/library modules" entry.
I get a link error with gcc/g++ (GNU GCC). What should I do?
  • For C apps: use soapcpp2 option -c to generate C code, use only the package's .c files, link with libgsoap.a (-lgsoap) or use the lib's source stdsoap2.c (and dom.c when applicable).
  • For C++ apps: there is no need to change any of the gSOAP package .c source file extensions into .cpp extensions, except for your main source program which must have the .cpp extension for the final linkage. For example, suppose our myprog.cpp client app uses the WS-Addressing and WS-ReliableMessaging plugins and the xsd:duration custom serializer:
  • soapcpp2 -a -L -S -I $GSOAPHOME -I $GSOAPHOME/import myprog.h
    g++ -I $GSOAPHOME -o myprog myprog.cpp plugin/wsaapi.c plugin/wsrmapi.c custom/duration.c soapC.cpp soapClient.cpp -lgsoap++
    
    Thus, you must use g++ to compile all C and C++ source code files to force C++ linking rules, as shown above.
  • All plugin sources are located in the plugin directory and should be compiled and linked with your C or C++ app. Custom types and serializers are located in the custom directory and when a custom type's serializer is used the course file must be compiled and linked.
The build fails when the Bison tool is invoked and produces a signal 13. What should I do?
You need to install a newer version of m4 from GNU m4. If the build then fails due to missing libsigsegv, install libsigsegv.
My code segfaults. What can I do?
  • Make sure that the gSOAP run-time environment (struct soap) is initialized by calling soap_init(&soap).
  • When working with C++ applications, make sure that you don't include the gSOAP header file directly in your C++ sources. You must use the gSOAP-generated soapH.h file instead, which includes the proper class extensions with virtual serialization methods.
  • Make sure you don't pass the gSOAP run-time environment (struct soap) by value to your application functions. Always pass struct soap by reference or pointer, just like the internal gSOAP functions do. In case you need to make a copy of it, use soap_copy().
  • Make sure all pointers that occur in the data structures that are passed as parameters to remote methods are initialized, i.e. pointers should be NULL or point to a valid object.
  • Make sure all class instances that are passed as parameters to remote methods are initialized, i.e. the virtual method tables (VMTs) must be set.
  • Make sure that no two (or more) threads access the same gSOAP run-time environment (struct soap) concurrently, i.e. use separate run-time environments in threads.
  • Remove all calls to soap_destroy() and soap_end() and rerun to check if the segfault results from gSOAP's garbage collect cleanup.
  • If the segfault occurs in the soap_destroy() cleanup, remove all deallocation calls in the class' destructors to avoid duplicate deallocations (one by the destructor and one by gSOAP's cleanup). Compensate the elimination of deallocation calls by allocating data solely with soap_malloc() and soap_new_Class() routines in your code. Alternatively, you can use soap_unlink() in the class destructors to unlink the data from gSOAP's deallocation chain before deallocating it in the class destructor (see the gSOAP documentation on soap_malloc(), soap_new_Class(), and soap_unlink() in class methods).
  • If the segfault occurs in the soap_end() cleanup, then it is likely that data is already deallocated with free() in your code and deallocated again in soap_end(). Use soap_unlink() to unlink the data from gSOAP's deallocation chain before freeing it up.
  • When you use OpenSSL and/or Zlib, please compile all sources with WITH_OPENSSL and/or WITH_GZIP to ensure that the soap struct's layout is identical in all places where it is used.
The time_t deserialization appears to be incorrect, because the time_t value is off by one or more hours. How can I fix this?
Some platforms do not support timegm() to convert time expressed in UCT to time_t values. Therefore, the gSOAP kernel uses gettimeofday() or ftime() with mktime() to deserialize xsd:dateTime values into time_t. As a result, when the timezone on the machine on which gSOAP runs is set incorrectly, this will cause the time_t value to be off by one or more hours. Unfortunately, the problem is more difficult with Solaris 8 and earlier, because Solaris does not implement the DST settings of gettimeofday() and ftime() correctly.
My application recieves a "Broken Pipe" error. What should I do to fix this?
A "broken pipe" signal SIGPIPE is OS dependent. It is triggered when a peer closes a connection unexpectedly on Linux and Unix variants. When the signal is not caught, the application exits. To prevent this, use one of the following three methods:
soap.accept_flags = SO_NOSIGPIPE;  /* some systems accept this */
soap.socket_flags = MSG_NOSIGNAL;  /* others need this */
signal(SIGPIPE, sigpipe_handler);  /* and when the above are not supported, we use a sigpipe handler */
where the sigpipe_handler is defined as a no-op function:
void sigpipe_handler(int x) { }
My Web service application crashes. What to do?
First determine if the application crashes in the gSOAP code. Then check:
  • If your application crashes in the serialization code while sending data, it is very likely that the serializer encountered an undefined pointer member in a struct or class to serialize to XML. Make sure the data to be serialized is properly set and contains valid data for all struct/class members (transient members are not serialized and can be undefined). Set struct/class pointer members to NULL when not in use. To ease this burden, use the soap_default_T() generated functions for structs T and T::soap_default() function members of classes T to set the struct/class to default values.
  • If your server application crashes after invoking a service operation while returning data to the client, see the next FAQ item below.
  • If the crash occurs in the deserialzer while reading data, then check if you declared in the gSOAP header file a SOAP array (or __ptr and __size pair) of an array of class instances. It is strongly advised to use pointers to class instances in arrays (using T **__ptr to point to an array of pointers to class T instances), otherwise class instances might be copied in memory to collect them into arrays which on some platforms may fail.
  • Make sure to #include "soapH.h" in each of your source code files. The soapcpp2 tool adds serializers to classes, so it is important to use the classes redefined in soapH.h (soapStub.h). If your project does not allow class redefinitions, use the volatile qualifier with your class definition in the .h file for soapcpp2.
  • Make sure the gSOAP release versions of stdsoap2.h and libgsoap you link with are the same.
  • If none of the above applies and the crash occurs in the gSOAP code then contact the author with an example source code program that reproduced the problem.
I wrote a Web Service that has a method that returns a data structure allocated on the stack. My service returns the wrong values and/or crashes. How can I allocate temporary data?
Use function:
void *soap_malloc(size_t n); // gSOAP 1.X
void *soap_malloc(struct soap *soap, size_t n); // gSOAP 2.X
These functions allocate memory on the heap that will be released upon calling soap_end() after soap_serve(). For example, in a gSOAP service:
main()
{ ...
  soap_serve(&soap);
  soap_end(&soap);
  ...
}
An example remote method that allocates a temporary string is:
int ns__itoa(struct soap *soap, int i, char **a)
{ *a = (char*)soap_malloc(soap, 11);
  sprintf(*a, "%d", i);
  return SOAP_OK;
}
Note that you don't want to use local function variables to store values such as strings, because the values are allocated on the stack and deallocated when the function returns while serialization of the values takes place after return. This allocation with soap_malloc() can also be used to allocate strings for the SOAP Fault data structure, for example:
int ns__mymethod(struct soap *soap, ...)
{ ...
  if (exception)
  { char *message = (char*)soap_malloc(soap, 1024);
    char *details = (char*)soap_malloc(soap, 1024);
    sprintf(message, ...);
    sprintf(details, ...);
    return soap_receiver_fault(soap, message, details);
  }
  ...
}
I get a tag mismatch error and/or data appears to be ignored when receiving SOAP/XML messages.
Check that your gSOAP header file includes //gsoap directives to define XML namespaces. These namespace bindings will be added to a .nsmap file generated by the gSOAP compiler (or you can write your own .nsmap file). The gSOAP header file requires a one-to-one correspondence between namespace prefix and the namespace name. Therefore, a namespace name may not occur more than once in a //gsoap ... service namespace directive.
My code appears to ignore data when receiving SOAP/XML messages. How can I detect unrecognized element tags at run time and let my application fault?
SOAP allows optional elements to be ignored. As a side effect, a namespace mismatch and/or tag name mismatch will result in dropping the element. If the namespace and/or tag name are defined correctly, data will never be dropped at run time. To assist debugging and to catch dropped elements, set the soap_set_imode(&soap, SOAP_XML_STRICT) flag. This will enforce strict validation of messages to catch (unknown elements and namespaces. Another way to control the dropping of unknown elements is to define the fignore callback. For example:
{ struct soap soap;
  soap_init(&soap);
  soap.fignore = mustmatch; // overwrite default callback
  ...
  soap_done(&soap);	// reset callbacks
}
int mustmatch(struct soap *soap, const char *tag)
{ return SOAP_TAG_MISMATCH;	// every tag must be handled
}
The tag parameter contains the offending tag name. You can also selectively return a fault:
int mustmatch(struct soap *soap, const char *tag)
{ if (soap_match_tag(soap, tag, "ns:login*"))	// all tags in namespace "ns" that start with "login" are optional
    return SOAP_OK;
  return SOAP_TAG_MISMATCH;	// every other tag must be understood (handled)
}
SOAP 1.1 allows the return parameter elements of a SOAP response to be 'anonymous'. How can I tell gSOAP to use anonymous return parameter names?
For gSOAP 2.1.11 and higher, specify the function prototype without parameter names. For earlier gSOAP releases, you can prefix the return parameter names with an underscore ('_'). For example:
int ns__mymethod(..., int *_return); // single anonymous output parameter
and
int ns__mymethod(..., struct ns__mymethodResponse{int _return1; char *_return2; ...} *result); // multiple output paramers
How can I tell gSOAP to ignore certain declarations of types in a header file so I can write class methods that use parameters of these types?
You can provide the type declarations in the header file and use the 'extern' qualifier or enclose the type declarations between [ and ] to make them 'transient', i.e. non-serializable. For example:
extern class ostream; // can't be (de)serialized so must be declared a transient type
class ns__foo
{ public:
  char *s;
  struct soap *soap; // special field: already transient
  ns__foo();
[ ns__foo(const char *t); // transient constructor
  print(ostream &s); // transient method
]
};
with e.g. the following implementation of ns__foo:
 
ns__foo::ns__foo(const char *t)
{ s = (char*)soap_malloc(soap, strlen(t)+1);
  strcpy(s, t);
}
The 'struct soap* soap' field in this class is a special field set by gSOAP's deserializers and the gSOAP-generated soap_new_ns__foo() function.
How can I tell gSOAP to use primitive XSD schema types or SOAP-ENC schema types?
Use typedef declarations for primitive types in the header file input to the compiler. This is important for SOAP RPC encoding style. For example, to declare a XSD schema string type, declare typedef char *xsd__string; and use the xsd__string type in remote method parameters and other compound data structures. See the documentation for more details on primitive XSD schema types and the section on doc/literal encoding. The declaration of SOAP-ENC schema types is similar. For example, typedef char *SOAP_ENC__string declares a SOAP-ENC:string schema type.
How do I debug a SOAP client?
Compile stdsoap2.cpp (or stdsoap2.c for C) with compiler option -DDEBUG (/DDEBUG in MSVC++) to enable the DEBUG macro. You can also uncomment "#define DEBUG" in stdsoap2.h and recompile stdsoap2.cpp/stdsoap2.c. When you run your application, three files are created in the current directory: SENT.log, RECV.log, and TEST.log. All output messages are appended to SENT.log, all input messages are appended to RECV.log, and TEST.log contains various logging messages generated by the gSOAP runtime environment. Alternatively, you can use the example plugin code provided in the distribution package in extras/plugin.h to develop an application that can selectively log input and output messages. In addition, you can use a simple trick to inspect a client request message by leaving the endpoint URL empty ("" string). This will send the request message to stdout. The client application expect the response to be available from stdin. So, unless you provide a response message using redirect e.g. from a file or a service application using Unix pipes, you will have to terminate the client application.
How do I debug a Web Service installed as a CGI application?
1. Uncomment "#define DEBUG" in stdsoap.h and recompile your Web Service application. Install the executable as a CGI application on your Web server. Create three empty files in the same directory: SENT.log, RECV.log, and TEST.log. They should have read and write permissions for "other" (i.e. for everyone). These files will log all accesses to the CGI application. Do not forget to remove them later and turn off debugging.
2. Alternatively, compile your Web Service application. Create a file with the SOAP request message and use file redirect to input this message as standard input to the executable, which should print the SOAP response message.
Does gSOAP support multi-threading?
Yes, gSOAP 2.x does. There are differences in the API's used in gSOAP 2.X compared to gSOAP 1.X to support multi-threading. Section 3 of the gSOAP 2.X documentation details these differences.
I wrote a client and service that exchange strings, but I get garbage or I get only one character communicated and not the entire string!?
Your function prototype is probably similar to "mymethod(char *in, char *out)". The output parameter "out" is a pointer to a byte instead of a pointer to a string (output parameters must be pointers or references to a type). The correct way to do this is: "mymethod(char *in, char **out)" or mymethod(char *in, char *&out)".
I wrote a client and service that exchange strings declared as char[N], but I get an array of N bytes in the payload!?
If you use a fixed-size array of chars, the array is (de)marshalled as an array of bytes and not a string. Always use char* for strings. gSOAP does not and will not support fixed-size string arrays because the actual data transmitted may not fit the array which can lead to data loss.
I wrote a remote method declaration and the compiler gives a syntax error for parameter names that are keywords such as 'return'
Use trailing underscores in parameter names, type names, struct fields, class members, etc. to avoid name clashes with keywords. The trailing underscores in identifier names are invisible in the SOAP/XML payload. For example "mymethod(int &return_);" declares a remote method with output parameter "return_" which will be (de)serialized in XML as "return".
How do I write a remote method that has no input parameters?
Just specify one output parameter. Some C/C++ compilers will not compile the gSOAP-generated codes due to an empty struct created by gSOAP. To circumvent this problem, use void* as a dummy input parameter, e.g. "ns__myMethod(void*_, int &return_);". The void* parameter will not be (de)serialized.
I have a remote method with a response struct that is also used as a type elsewhere in my header file, but now my WSDL is incomplete because the type is not defined in the WSDL (an element definition appears instead).
A response struct/class is not a type but a placeholder or wrapper for the result parameters. So you cannot use this struct/class anywhere else in your type definitions, since it will be defined as a schema element rather than a schema type. For example:
struct ns__data { ... };
int ns__example(..., struct ns__data *out);
where the ns__data struct contains the result parameters of the method. The struct is translated into an element definition in the generated WSDL to support doc/lit style messaging. As you can see, this means that ns__data cannot be used as a type anywhere else in your header file. To work around this problem, use:
struct ns__data { ... };
int ns__example(..., struct ns__exampleResponse { struct ns__data out; } *out);
Now we have a type ns__data and a response struct for the method results.
How do I write a remote method that has no output parameters?
Specify an empty struct output parameter. For example: "ns__myMethod(..., struct ns__myMethodResponse { } &response)". Some C/C++ compilers will not compile the empty struct. To circumvent this problem, use void* as a dummy field, e.g. "ns__myMethod(..., struct ns__myMethodResponse { void*_; } &response)" The void* field will not be (de)serialized.
How can I use (wide character) strings for doc/literal encoding to (de)serialize any form of XML?
Declare:
typedef char *XML;
or
typedef wchar_t *XML;
and use either XML type for mixed-content strings (strings that contain XML).
How do I add SOAP Headers to my messages?
In gSOAP 1.X set the global "soap_header" variable to point to a SOAP_ENV__Header data structure. The declaration of the fields in this data structure can be specified in the header file input to the compiler for customized header processing.
In gSOAP 2.X set the "header" field of the runtime environment variable (e.g. "soap") to point to a "struct SOAP_ENV__Header" (e.g. "soap.header = malloc(sizeof(struct SOAP_ENV__Header))". The declaration of the fields in this data structure can be specified in the header file input to the compiler.
How do I add SOAP Headers to my messages?
In gSOAP 1.X set the global "soap_header" variable to point to a SOAP_ENV__Header data structure. The declaration of the fields in this data structure can be specified in the header file input to the compiler for customized header processing.
How do I use gSOAP for the ONVIF specifications?
Use gSOAP 2.8.10 and up. In the typemap.dat file used by wsdl2h, add:
#	ONVIF recommended prefixes
tds	= "http://www.onvif.org/ver10/device/wsdl"
tev	= "http://www.onvif.org/ver10/events/wsdl"
tls	= "http://www.onvif.org/ver10/display/wsdl"
tmd	= "http://www.onvif.org/ver10/deviceIO/wsdl"
timg	= "http://www.onvif.org/ver20/imaging/wsdl"
trt	= "http://www.onvif.org/ver10/media/wsdl"
tptz	= "http://www.onvif.org/ver20/ptz/wsdl"
trv	= "http://www.onvif.org/ver10/receiver/wsdl"
trc	= "http://www.onvif.org/ver10/recording/wsdl"
tse	= "http://www.onvif.org/ver10/search/wsdl"
trp	= "http://www.onvif.org/ver10/replay/wsdl"
tan	= "http://www.onvif.org/ver20/analytics/wsdl"
tad	= "http://www.onvif.org/ver10/analyticsdevice/wsdl"
tdn	= "http://www.onvif.org/ver10/network/wsdl"
tt	= "http://www.onvif.org/ver10/schema"
#	OASIS recommended prefixes
wsnt	= "http://docs.oasis-open.org/wsn/b-2"
wsntw	= "http://docs.oasis-open.org/wsn/bw-2"
wsrfbf	= "http://docs.oasis-open.org/wsrf/bf-2"
wsrfr	= "http://docs.oasis-open.org/wsrf/r-2"
wsrfrw  = "http://docs.oasis-open.org/wsrf/rw-2"
wstop	= "http://docs.oasis-open.org/wsn/t-1"
#	WS-Discovery 1.0 remapping
wsdd10__HelloType		= | wsdd__HelloType
wsdd10__ByeType			= | wsdd__ByeType
wsdd10__ProbeType		= | wsdd__ProbeType
wsdd10__ProbeMatchesType	= | wsdd__ProbeMatchesType
wsdd10__ProbeMatchType		= | wsdd__ProbeMatchType
wsdd10__ResolveType		= | wsdd__ResolveType
wsdd10__ResolveMatchesType	= | wsdd__ResolveMatchesType
wsdd10__ResolveMatchType	= | wsdd__ResolveMatchType
#	SOAP-ENV mapping
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
SOAP_ENV__Fault		= | struct SOAP_ENV__Fault
SOAP_ENV__Detail	= | struct SOAP_ENV__Detail
SOAP_ENV__Code		= | struct SOAP_ENV__Code
SOAP_ENV__Subcode	= | struct SOAP_ENV__Subcode
SOAP_ENV__Reason	= | struct SOAP_ENV__Reason
At the command line prompt, run wsdl2h on the ONVIF WSDLs. For example, the device management and event specifications:
$ wsdl2h -P -x -o onvif.h http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl http://www.onvif.org/onvif/ver10/event/wsdl/event.wsdl
$ soapcpp2 -I import onvif.h
Note that the specifications are substantial in size. Option wsdl2h -P removes unnecessary class hierarchy dependences on the root type xsd__anyType. This option will reduce the code size. Option -x removes extensibility elements (xsd:anyAttribute attributes and xsd:any elements). If attribute and element extensions to a complexType are needed, then use the typemap.dat file to add these as additional optional members. For example, to extend tt__AudioDecoderConfigurationOptionsExtension complexType class with an element Address of type tt:IPAddress, add to typemap.dat:
tt__AudioDecoderConfigurationOptionsExtension = $ tt__IPAddress Address;
If it appears that multiple service operations are generated with the same namesuch as GetServices and GetServices_ then remove http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl from the command line list of URLs because this WSDL is already imported by another WSDL. Please note that wsdl2h 2.8.10 and earlier versions generate ns1, ns2, ns3, etc prefixes when multiple service bindings are given for service operations. This will be changed in gSOAP 2.8.11 and up. The change can be made in 2.8.10 and earlier versions by modifying gsoap/wsdl/service.cpp:70
void Definitions::analyze(const wsdl__definitions &definitions)
{ // Analyze WSDL and build Service information
  int binding_count = 0;
  // Determine number of relevant SOAP service bindings
  if (service_prefix)
  { for (vector::const_iterator i =
definitions.binding.begin(); i != definitions.binding.end(); ++i)
    { for (vector::const_iterator j =
(*i).operation.begin(); j != (*i).operation.end(); ++j)
      { if ((*j).operationPtr() && (*j).input && (*j).input->soap__body_)
        { binding_count++;
          break;
        }
      }
    }
  }
  else
    binding_count = 1; // Put all operations under a single binding
  ...
then rebuild wsdl2h. With this change, option wsdl2h -Nns reverts back to the old behavior.
Who is Genivia inc?
gSOAP is copyrighted and owned by Robert A. van Engelen. Genivia inc. is a private company founded by Robert A. van Engelen to distribute licensed versions of gSOAP and to provide software support and for consulting services.