Genivia Home Documentation
gSOAP user guide

updated by Robert van Engelen
 
gSOAP user guide

User guide

Copyright (c) 2000-2025, Genivia Inc.
All rights reserved.

Introduction

The gSOAP toolkit offers C/C++ tools and libraries to implement efficient and secure SOAP, XML, JSON and REST client and service Web API applications. The tools also offer XML data bindings for C and C++ to generate XML serializers to efficiently read and write C/C++ data to and from files and streams.

The gSOAP wsdl2h tool consumes WSDL and XSD schema files to converts them to C/C++ source code to implement XML messaging infrastructures. This frees the developer to focus on application functionality rather than on infrastructure.

More specifically, the wsdl2h tool consumes WSDLs to generate a C or C++ interface header file, which uses a developer-friendly C/C++ header file syntax. This allows developers to inspect Web services and XML schemas from a functionality point of view, rather than getting bogged down into the underlying SOAP-based infrastructure details of WSDLs and XSDs.

The soapcpp2 tool generates all the Web service binding source code with XML serializers necessary to quickly develop server-side and client-side Web service APIs.

The soapcpp2 tool can also be used to produce, rather than consume, WSDL and XSD files to deploy XML Web services or to develop XML applications. This approach allows the deployment of legacy C/C++ applications as services. Simply describe the Web API in a C or C++ interface header file for the soapcpp2 tool to generate the C/C++ source code that glues everything together.

Besides SOAP-based services, also non-SOAP XML and JSON REST services can be implemented with the gSOAP tools. Either described by WSDLs or by XML schemas converted to C/C++ source code by wsdl2h, or by using the JSON libraries included with gSOAP to develop JSON applications.

Furthermore, the gSOAP tools can be just as easily used to develop C/C++ applications that efficiently consume and produce XML by leveraging XML data bindings for C/C++ based on XML schemas. Basically, an XML schema has an equivalent set of C/C++ data types for the components described by the schema. So XML schema strings are just C/C++ strings, XML schema enumerations are C/C++ enums, XML schema complex types are just structs and classes in C/C++, and so on. This enhances the reliability and safety of XML applications, because type-safe serializable C/C++ data types are serialized and validated in XML automatically.

This XML data binding means that your XML data is simply represented as C/C++ data. Reading and writing XML is a lot easier than using a DOM or SAX library for XML. This is not more expensive or more complex than it sounds. In fact, the generated XML serializers are very efficient to parse and validate XML and may run more than 30 times faster than validating XML parsers such as Apache Xerces C++.

In summary, gSOAP offers a type-safe and transparent approach to develop XML applications that has proven to be quicker to develop (by auto-coding), safer (by XML validation and type-safety), more reliable (by auto-generation of XML test messages and warnings), and higher performing (by efficient serializers and XML parsers generated in C/C++), compared to DOM and SAX libraries.

This user guide explains the gSOAP tools and libraries. This user guide and additional documentation for the growing number of gSOAP plugins can be found at https://www.genivia.com/doc. A getting-started guide for developers is available at https://www.genivia.com/dev.html with a tutorial on common topics at https://www.genivia.com/tutorials.html. Various examples ranging from simple calculator service APIs to very large protocols spanning dozens of WSDLs can be found at https://www.genivia.com/examples.html. For frequently asked questions see https://www.genivia.com/resources.html for help.

🔝 "" "Back to table of contents"

Notational conventions

The typographical conventions used by this document are:

  • Courier denotes C and C++ source code.
  • Courier denotes XML content, JSON content, file and path names, and URIs.
  • Courier denotes HTTP content, text file content, and shell commands with command line options and arguments.

The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC-2119.

🔝 "" "Back to table of contents"

Tooling characteristics

  • Safety: the tools generate type-safe XML serialization functions for native and user-defined C and C++ data structures.
  • Protocols: WSDL 1.1, WSDL 2.0, REST, SOAP 1.1, SOAP 1.2, SOAP RPC encoding style, SOAP document/literal style, SOAP-over-UDP, WS-Security, WS-Addressing, WS-ReliableMessaging, WS-Discovery, WS-Trust, WS-Policy, JSON REST/RPC, XML-RPC, Atom and RSS. JSON is supported as a library bundled with the XML-RPC library to switch between XML-RPC and JSON protocols (since these are similar, speaking data wise). For more details, see the gsoap/samples/xml-rpc-json folder in the gSOAP package and the XML-RPC and JSON documentation.
  • SOAP: implements the full range of SOAP 1.1/1.2 specifications, including RPC encoding and document/literal messaging styles.
  • XSD: supports all XML schema 1.0 and 1.1 schema type constructs and has been tested against the W3C XML Schema Patterns for Databinding Interoperability working group.
  • XML: implements a fast schema-specific XML pull parser that does not require intermediate storage of XML in a DOM to deserialize data.
  • HTTP: HTTP 1.0/1.1, IPv4 and IPv6, HTTPS (requires OpenSSL 3.0 or the latest or GNUTLS or WolfSSL), cookies, authentication, Zlib deflate and gzip compression, and connecting through HTTP proxies.
  • Attachments: MIME (SwA), DIME, and MTOM attachments are supported. Streaming capabilities to direct the data stream to/from resources using user-defined callbacks. gSOAP is the only toolkit that supports streaming MIME, DIME, and MTOM attachment transfers, which allows you to exchange binary data of practically unlimited size in the fastest possible way by streaming, while ensuring the usefulness of XML interoperability.
  • Debugging: compilation of client and service applications in #DEBUG mode traces their engine activity for debugging, verifies memory usage (leak detection), and saves message logs for inspection.
  • Testing: soapcpp2 -T generates server source code that automatically implements echo message services for testing. The testmsgr tool generates XML messages from message templates for server-side and client-side black-box testing, see Test Messenger documentation. In addition, the soapcpp2 tool generates sample SOAP/XML input and output messages for verification and testing.
  • Speed: the soapcpp2-generated high-performance XML serializers are ideal for building efficient Web services that are compute-intensive and are therefore best written in C or C++.
  • Portability: source code is portable and compiles on Windows, Unix, Linux, Mac OS X, Symbian, VXWorks, and embedded systems that run WinCE, Symbian, embedded Linux, and so on. The memory footprint of gSOAP client and service applications is small.
  • Footprint: input and output buffering is used to increase efficiency and reduce memory usage. Input and output messages are not fully buffered or stored in a DOM unless required or specified. As a result, large messages can be transmitted by low-memory devices.

🔝 "" "Back to table of contents"

API documentation modules

The API documentation is broken down into the following functional documentation modules that drill down into the lower-level API of macros, functions, context and context variables, plugins and more:

Debugging and loggingThis module defines compile-time flags and functions for run-time debugging and logging
WITH_MACRO compile-time flagsThis module defines the WITH_MACRO compile-time flags to configure the engine build
SOAP_MACRO compile-time valuesThis module defines the SOAP_MACRO compile-time values to configure the engine build
SOAP_MACRO run-time flagsThis module defines the SOAP_MACRO run-time soap_mode flags to set the engine mode
SOAP_MACRO run-time error codesThis module defines the SOAP_MACRO run-time soap_status error codes returned by functions and stored in soap::error
Context with engine stateThis module defines the soap context structure with the engine state and functions to allocate, initialize, copy and delete contexts
Callback functionsThis module defines the callback functions of the soap context to modify its behavior, as is done by plugins
SSL/TLS context and functionsThis module defines functions to set the SSL/TLS context for HTTPS and WS-Security
HTTP and IO functionsThis module defines functions for HTTP operations and functions for receiving and sending data
HTTP cookie functionsThis module defines functions to set and get HTTP cookies at the server side
Conversion functionsThis module defines conversion functions of values of various types to and from strings
XML namespace tablesThis module defines the Namespace XML namespace structure and function to activate a table
Header structure and functionsThis module defines the SOAP_ENV__Header structure and soap_header function to allocate the header
Fault structure and functionsThis module defines the SOAP_ENV__Fault structure and functions to set and get fault information
DIME attachment functionsThis module defines functions to set and get DIME attachments
MIME attachment functionsThis module defines functions to set and get MIME/MTOM attachments
Plugins and plugin registry functionsThis module defines plugin registry functions to register plugins
Thread and mutex functionsThis module defines portable thread and mutex functions
Miscellaneous functionsThis module defines other useful functions

🔝 "" "Back to table of contents"

Getting started

To start using gSOAP, you will need:

The gSOAP source code package includes:

  • The wsdl2h data binding tool that converts WSDLs and XSDs to generate interface header files for soapcpp2. The source code of the wsdl2h tool is located in gsoap/wsdl.
  • The soapcpp2 code generation tool that takes an interface header file and generates the C/C++ Web service binding implementation source code. The source code of the soapcpp2 tool is located in gsoap/src.
  • The run-time engine gsoap/stdsoap2.h and source code gsoap/stdsoap2.c for C and gsoap/stdsoap2.cpp for C++. These are compiled into the C libraries gsoap/libgsoap.a (without OpenSSL/GNUTLS for SSL/TLS), gsoap/libgsoapssl.a (with OpenSSL/GNUTLS for SSL/TLS and with gsoap/dom.c for DOM API), and the C++ libraries gsoap/libgsoap++.a (without OpenSSL/GNUTLS for SSL/TLS), gsoap/libgsoapssl++.a (with OpenSSL/GNUTLS for SSL/TLS and with gsoap/dom.cpp for DOM API). There are two more versions of these libraries with HTTP cookies enabled.
  • Several examples of gSOAP applications and other development tools that are build with wsdl2h and soapcpp2 are located in gsoap/samples.
  • XML DOM API and the domcpp code generation tool located in gsoap/samples/dom, see also the XML DOM API and domcpp documentation.
  • JSON and XML-RPC libraries and the jsoncpp code generation tool located in gsoap/samples/xml-rpc-json, see also the XML-RPC and JSON documentation.
  • An XML Web API testing tool located in gsoap/samples/testmsgr, see also the Test Messenger documentation.
  • Plugins to enhance the capabilities of the engine and to support WS protocols such as WS-Security, WS-Addressing, WS-ReliableMessaging, and WS-Discovery. The plugins are located in gsoap/plugin and gsoap/mod_gsoap. Most but not all plugins are imported into interface header files for soapcpp2 with the #import directive. See also API documentation Module Plugins and plugin registry functions.
  • Custom serializers for several C and C++ types to enhance the capabilities of XML serialization, located in gsoap/custom. Custom serializers are imported into interface header files for soapcpp2 with the #import directive. This is usually done via a typemap.dat file for wsdl2h that specifies bindings for XML schema types to C/C++ types, including custom serializers when desired.

The wsdl2h and soapcpp2 tools and the gSOAP libraries are build with ./configure and make, see the download and installation page https://www.genivia.com/downloads.html for the most recent versions of gSOAP and gSOAP software installation details. The examples and other tools are build with ./configure --enable-samples and make.

Non-SSL-enabled (that is, not HTTPS capable) versions of the binaries of the wsdl2h and soapcpp2 tools are also included in the gSOAP package in gsoap/bin for Windows and Mac OS platforms. The SSL-enabled and HTTPS-capable wsdl2h tool is only available for download from https://www.genivia.com/downloads.html with a commercial-use license and download key.

Although gSOAP tools are available in binary format for several platforms, the code generated by these tools is equivalent. This means that the generated source code files can be transferred between platforms and locally compiled.

The examples given in this document do not require the libraries of the engine to be build, but rather show the use of the source code: gsoap/stdsoap2.c and gsoap/dom.c (or gsoap/stdsoap2.cpp and gsoap/dom.cpp for C++). Using the source code instead of the libraries gives more control when we use the -DWITH_MACRO and -DSOAP_MACRO compile-time options, see also Modules WITH_MACRO compile-time flags and SOAP_MACRO compile-time values.

🔝 "" "Back to table of contents"

Where to find examples

Introductory examples can be found online at https://www.genivia.com/dev.html. Additional examples can be found online at https://www.genivia.com/examples.html.

The gSOAP package also contains numerous examples in the gsoap/samples directory. Run make inside these directories to build the example applications. The examples are meant to demonstrate basic to advanced features of gSOAP. Some examples are actually development tools and libraries, such as Test Messenger located in gsoap/samples/testmsgr to test XML Web APIs, the XML DOM API and domcpp located in gsoap/samples/dom to generate XML DOM API source code from XML files, the JSON API and jsoncpp located in gsoap/samples/xml-rpc-json to generate JSON API source code from JSON files.

Advanced examples include a streaming MTOM attachment server and client application demonstrate high-performance file exchanges, located in gsoap/samples/mtom-stream. An SSL-secure Web server application demonstrates the generation of dynamic content for Web browsing and Web services functionality at the same time, located in gsoap/samples/webservice.

🔝 "" "Back to table of contents"

Creating a SOAP/XML client application

This section explains the basics to develop a SOAP/XML client application in C and C++. We refer to https://www.genivia.com/dev.html for additional introductory examples of SOAP/XML, XML REST and JSON applications in C and C++.

The wsdl2h tool imports one or more WSDLs and XML schemas and generates a gSOAP interface file for soapcpp2 with familiar C/C++ header file syntax to define the Web service operations and the C/C++ data types. The soapcpp2 tool then takes this header file and generates XML serializers for the data types (soapStub.h, soapH.h, and soapC.cpp), the client-side stub functions (soapClient.cpp), and server-side skeleton functions (soapServer.cpp).

The soapcpp2 tool can also generate WSDL definitions to implement a service from scratch, i.e. without defining a WSDL first. This "closes the loop" in that it enables Web services development from WSDL or directly from a set of C/C++ operations declared as functions in an interface header file for soapcpp2 without the need for users to be experts in WSDL and XSD.

You only need to follow a few steps to execute the tools from the command line or using a Makefile (see also MSVC++ project examples in the gsoap/samples directory with tool integration in the MSVC++ IDE). For example, to generate code for the calculator Web service, we run the wsdl2h tool from the command line on the URL of the WSDL and use `wsdl2h -o calc.h` option `-o calc.h` to specify the calc.h interface file to output:

 wsdl2h -o calc.h http://www.genivia.com/calc.wsdl

This generates the calc.h service definition interface file with service operation definitions and types to pass with the operation parameters. This interface file is then input to the soapcpp2 tool to generate the stub and skeleton source code and XML serialization functions. The calc.h file includes documentation extracted form the WSDL and introductions to process the file with soapcpp2. You can use Doxygen (http://www.doxygen.org) to automatically generate the documentation pages for your development from the generated calc.h interface file. To generate a markdown report for your client, use soapcpp2 -r option -r which has more details than the calc.h file.

In this example we will develop a C++ API for the calculator service. By default, the wsdl2h tool generates C++ with containers and other C++ std data types. To build without C++ containers and other std types, use `wsdl2h -s` option `-s`:

 wsdl2h -s -o calc.h http://www.genivia.com/calc.wsdl
Note
Visual Studio IDE users should make sure to compile all gSOAP source code files in C++ compilation mode. If you migrate to a project file .vcproj, please set CompileAs="2" in your .vcproj file.

We have not yet generated the stub functions and serializers for our C++ client application to invoke remote service operations. To do so, we run the soapcpp2 tool as follows:

 soapcpp2 -j -C -Iimport calc.h

Option -j (and alternatively option -i) indicates that we want C++ proxy and server objects that include the client (and server) code, option -C indicates client-side only files are generated (soapcpp2 generates both client stub functions and server skeleton functions by default). Option -I is needed to import the stlvector.h file from the gsoap/import directory located in the gSOAP source code package to support serialization of vectors, when applicable.

We use the generated soapcalcProxy class declared and defined in soapcalcProxy.h and soapcalcProxy.cpp, and calc.nsmap XML namespace mapping table to access the Web service. The soapcalcProxy.h file includes documentation on the proxy class. The soapcalcProxy class is a proxy to invoke the remote service:

// File: calclient.cpp
#include "soapcalcProxy.h"
#include "calc.nsmap"
int main()
{
calcProxy service;
double result;
if (service.add(1.0, 2.0, result) == SOAP_OK)
std::cout << "The sum of 1.0 and 2.0 is " << result << std::endl;
else
service.soap_stream_fault(std::cerr);
service.destroy(); // delete data and release memory
}
#define SOAP_OK
The soap_status code for no error (zero).
Definition stdsoap2.h:2392

To complete the build, compile the code above and compile this with the generated soapC.cpp and soapcalcProxy.cpp files, and link the engine with -lgsoap++:

c++ -o calcclient calcclient.cpp soapcalcProxy.cpp soapC.cpp -lgsoap++

Alternatively, compile gsoap/stdsoap2.cpp:

c++ -o calcclient calcclient.cpp soapcalcProxy.cpp soapC.cpp stdsoap2.cpp

Or after running the configure script the config.h file can be used to compile from source:

c++ -DHAVE_CONFIG_H -I. -I.. -o calcclient calcclient.cpp soapcalcProxy.cpp soapC.cpp stdsoap2.cpp

In both cases it is assumed that stdsoap2.h and the soapcpp2-generated soapcalcProxy.h, soapStub.h, soapH.h, and calc.nsmap files are located in the current directory.

Then run the example:

./calcclient
The sum of 1.0 and 2.0 is 3

To build a pure C application, use `wsdl2h -c` option `-c` and run soapcpp2 -C to generate the client stub functions and serializers:

 wsdl2h -c -o calc.h http://www.genivia.com/calc.wsdl
 soapcpp2 -C -Iimport calc.h

In this case our code uses a simple C function call to invoke the service and we also need to explicitly delete data and the context with soap_end and soap_free:

// File: calclient.c
#include "soapH.h" // include the generated declarations
#include "calc.nsmap" // include the generated namespace table
int main()
{
struct soap *soap = soap_new();
double result;
if (soap_call_ns__add(soap, 1.0, 2.0, &result) == SOAP_OK)
printf("The sum of 1.0 and 2.0 is %lg\n", result);
else
soap_destroy(soap); // delete managed objects
soap_end(soap); // delete managed data and temporaries
soap_free(soap); // finalize and delete the context
}
*Delete all dynamically allocated C objects managed by the specified ::soap context void soap_destroy(struct soap *soap)
*Delete all data from heap memory managed by the specified ::soap context and release the freed memory back to the heap void soap_end(struct soap *soap)
*Finalize and free the given ::soap context from unmanaged heap memory void soap_free(struct soap *soap)
void soap_print_fault(struct soap *soap, FILE *fd)
Print error message on the specified output.
Context with the engine state.
Definition stdsoap2.h:2929

To complete the build, compile the code above and compile this with the generated soapC.c and soapClient.c files, and link the engine with -lgsoap:

cc -o calcclient calclient.c soapClient.c soapC.c -lgsoap

Alternatively, compile gsoap/stdsoap2.c from source:

cc -o calcclient calclient.c soapClient.c soapC.c stdsoap2.c

Or after running the configure script the config.h file can be used to compile from source:

cc -DHAVE_CONFIG_H -I. -I.. -o calcclient calclient.c soapClient.c soapC.c stdsoap2.c

In both cases it is assumed that stdsoap2.h and the soapcpp2-generated soapStub.h, soapH.h, and calc.nsmap files are located in the current directory.

Then run the example:

./calcclient
The sum of 1.0 and 2.0 is 3

The calculator example is fairly simple and used here to illustrate the development steps from code generation to running the application. The development steps for large-scale XML applications is similar.

See https://www.genivia.com/dev.html for additional introductory examples of SOAP/XML, XML REST and JSON applications in C and C++. See https://www.genivia.com/examples and the examples located in the gSOAP source code package in the gsoap/samples directory.

🔝 "" "Back to table of contents"

Creating a SOAP/XML service application

This section explains the basics to develop a SOAP/XML service application in C and C++. We refer to https://www.genivia.com/dev.html for additional introductory examples of SOAP/XML, XML REST and JSON applications in C and C++.

Developing a service application is easy. In this example we will demonstrate a service deployed with the Common Gateway Interface (CGI) because it is a simple mechanism. This is not the preferred deployment mechanism. Because CGI is slow and stateless. FastCGI improves the speed of CGI applications, but is still stateless. Faster services can be developed as a stand-alone gSOAP HTTP/HTTPS servers as explained in this section further below.

To deploy services in a public and possibly hostile environment, we recommend the use of Apache module or IIS ISAPI extension to manage and protect services. An Apache module plugin and ISAPI extension plugin is included in the gSOAP package under gsoap/mod_gsoap. For details, see:

To deploy gSOAP stand-alone services in a public environment make sure to protect your service application as explained in Sections Safety guards and Timeout management for non-blocking operations. See also our tutorials https://www.genivia.com/tutorials.html with instructions to protect your online gSOAP Web APIs.

Let's get started. Suppose we want to implement a simple CGI-based service that returns the time in GMT. For this example we start with an interface header file for soapcpp2, currentTime.h which contains the service definitions. Such a file can be obtained from a WSDL using wsdl2h when a WSDL is available. When a WSDL is not available, you can define the service in C/C++ definitions in a newly created interface header file and let the soapcpp2 tool generate the source code and WSDL for you.

The currenTime service operation of our Web service has only one output parameter, which is the current time defined in our currentTime.h service specification:

// File: currentTime.h
//gsoap ns service name: currentTime
//gsoap ns service namespace: urn:currentTime
//gsoap ns service location: http://www.yourdomain.com/currentTime.cgi
int ns__currentTime(time_t& response);

Note that we associate an XML namespace prefix ns and namespace name urn:currentTime with the service WSDL and SOAP/XML messages. The gSOAP tools use a special convention for identifier names that are part of a namespace: a namespace prefix (ns in this case) followed by a double underscore __. This convention is used to resolve namespaces and to avoid name clashes. The ns namespace prefix is bound to the urn:currentTime namespace name with the //gsoap directive. The //gsoap directives are used to set the properties of the service, in this case the name, namespace, and location endpoint.

The service implementation for CGI simply requires a soap_serve call on a soap context created with ::soap_new. The service operations are implemented as functions, which are called by the service skeleton functions via the service request dispatcher soap_serve:

// File: currentTime.cpp
#include "soapH.h" // include the generated declarations
#include "currentTime.nsmap" // include the generated namespace table
int main()
{
// create soap context and serve one CGI-based request:
struct soap *soap = soap_new1(SOAP_XML_INDENT);
soap_destroy(soap); // delete managed class instances
soap_end(soap); // delete managed data and temporaries
soap_free(soap); // finalize and free the context
}
int ns__currentTime(struct soap *soap, time_t& response)
{
response = time(0);
return SOAP_OK;
}
#define SOAP_XML_INDENT
soap_mode XML output flag value to enable XML (and JSON) message indentation in messages sent
Definition stdsoap2.h:1937
*Bind and listen to a port SOAP_SOCKET soap_bind *(struct soap *soap, const char *host, int port, int backlog) * @returns the ` Accept a connection with a client SOAP_SOCKET soap_accept *(struct soap *soap) * @returns the ` Serve a pending request in soap_serve)(struct soap *soap) * @returns `
Definition stdsoap2.h:7455

Note that we pass the soap context with the engine context information to the service operation function as the first argument. The soap context comes in handy to determine properties of the connection and to dynamically allocate data with soap_malloc or with the generated soap_new_T functions for serializable types T that will be automatically deleted by calling soap_destroy and soap_end when the service operation is done and the service loop rolls over.

We run the soapcpp2 tool on the header file to generate the server-side code:

 soapcpp2 -S currentTime.h

and then compile the CGI binary:

 c++ -o currentTime.cgi currentTime.cpp soapServer.cpp soapC.cpp -lgsoap++

Alternatively, compile gsoap/stdsoap2.cpp from source:

 c++ -o currentTime.cgi currentTime.cpp soapServer.cpp soapC.cpp stdsoap2.cpp

Or after running the configure script the config.h file can be used to compile from source:

 c++ -DHAVE_CONFIG_H -I. -I.. -o currentTime.cgi currentTime.cpp soapServer.cpp soapC.cpp stdsoap2.cpp

To activate the service, copy the currentTime.cgi binary to your bin-cgi directory and set the proper file permissions.

The soapcpp2 tool generated the WSDL definitions currentTime.wsdl. You can use the WSDL to advertise your service. You don't need to use this WSDL to develop a gSOAP client. You can use the currentTime.h file with soapcpp2 -C option -C to generate client-side code.

Since CGI is very simple, a convenient aspect of CGI is that it exchanges messages over standard input and output. Therefore, you can run the CGI binary on the auto-generated example request XML file currentTime.currentTime.req.xml to test your server:

 ./currentTime.cgi < currentTime.currentTime.req.xml

and this displays the HTTP server response:

Status: 200 OK
Server: gSOAP/2.8
X-Frame-Options: SAMEORIGIN
Content-Type: text/xml; charset=utf-8
Content-Length: 460
Connection: close
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns="urn:currentTime">
<SOAP-ENV:Body>
<ns:currentTimeResponse>
<response>2018-10-25T17:17:03Z</response>
</ns:currentTimeResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The above approach works also for C. Just use soapcpp2 -c -S option -c in addition to the -S option to generate C code. Of course, in C we use pointers instead of references and the currentTime.h file should be adjusted to use C syntax and types.

Run soapcpp2 -r -c -S option -r to generate a soapReadme.md report. This report includes many details about the service operations and serializable C/C++ data types declared in the interface header file. This markdown file can be converted to HTML or other document formats with tools such as Doxygen.

A more elegant server implementation in C++ can be obtained by using soapcpp2 -j -S option -j (or option -i) to generate C++ client-side proxy and server-side service objects as classes that you can use to build clients and services in C++. The option removes the generation of soapClient.cpp and soapServer.cpp, since these are no longer needed when we have classes that implement the client and server logic:

 soapcpp2 -j -S currentTime.h

This generates soapcurrentTimeService.h and soapcurrentTimeService.cpp files, as well as auxiliary files soapStub.h, soapH.h, and soapC.cpp and currentTime.nsmap. The soapcurrentTimeService.h file includes documentation on the service class.

Now using the currentTimeService class we can improve the CGI service application:

// File: currentTime.cpp
#include "soapcurrentTimeService.h" // include the proxy declarations
#include "currentTime.nsmap" // include the generated namespace table
int main()
{
// create server and serve one CGI-based request:
currentTimeService server(SOAP_XML_INDENT);
server.serve();
server.destroy();
}
int currentTimeService::currentTime(time_t& response)
{
response = time(0);
return SOAP_OK;
}

We compile this with:

 c++ -o currentTime.cgi currentTime.cpp soapcurrentTimeService.cpp soapC.cpp -lgsoap++

Alternatively, compile gsoap/stdsoap2.c from source:

 c++ -o currentTime.cgi currentTime.cpp soapcurrentTimeService.cpp soapC.cpp stdsoap2.cpp

or after running the configure script the config.h file can be used to compile from source:

 c++ -DHAVE_CONFIG_H -I. -I.. -o currentTime.cgi currentTime.cpp soapcurrentTimeService.cpp soapC.cpp stdsoap2.cpp

and install the binary as a CGI application.

To run the server as a stand-alone iterative (i.e. non-multi-hreaded) server on port 8080 until a the accept times out or an error occurs:

if (server.run(8080) != SOAP_OK)
server.soap_stream_fault(std::cerr);

To run the server as a stand-alone iterative server on port 8080 while ignoring common errors until a TCP occurs:

while (server.run(8080) != SOAP_OK)
{
if (server.soap->error == SOAP_TCP_ERROR)
break;
server.soap_stream_fault(std::cerr);
}
#define SOAP_TCP_ERROR
A soap_status error code: a TCP/IP connection error occured.
Definition stdsoap2.h:2724

To implement stand-alone and multi-threaded services, see Sections How to create a stand-alone server and How to create a multi-threaded stand-alone service. These stand-alone Web Services handle multiple SOAP requests by spawning a thread for each request. Thread pooling is also an option. The use of Apache modules and ISAPI extensions to deploy gSOAP services is recommended to ensure load balancing, access control, tracing, and so on.

For more information on server-side service classes, see Section How to generate C++ server classes . For more information on client-side proxy classes, see Section How to generate C++ client proxy classes .

See https://www.genivia.com/dev.html for additional introductory examples of SOAP/XML, XML REST and JSON applications in C and C++. See https://www.genivia.com/examples and the gSOAP source code package gsoap/samples for more examples.

🔝 "" "Back to table of contents"

Introduction to XML data bindings

This section is a basic introduction to XML data bindings in C/C++. Because gSOAP offers many options to implement XML data bindings, we wrote a separate C and C++ XML data bindings document on this topic that contains an in-depth discussion of XML schema mappings to C/C++ types, using wsdl2h with typemap.dat to customize these bindings, memory management to allocate and release serializable types, and how to use soapcpp2 options to generate deep data structure copy and delete functions for serializable types.

Basically, the C/C++ XML data binding in gSOAP provides and automated mechanism to serialize any C and C++ data structure in XML and to deserialize XML back into C/C++ data structures. To facilitate XML data bindings, a WSDL or an XML schema (XSD file) can converted with wsdl2h into a set of serializable C or C++ data type declarations. These C/C++ type declarations can be readily incorporated into your application to manipulate XML directly as C/C++ data structures with much more ease than DOM or SAX. For example, XML schema strings are just C/C++ strings, XML schema enumerations are C/C++ enums, XML schema complex types are just structs or classes in C/C++, and so on. In this way, an automatic mapping between XML elements of the XML schema and members of a class is created. No DOM traversals and SAX events are needed.

More importantly, the XML C/C++ data binding makes XML manipulation type safe. That is, the type safety of C/C++ ensures that only valid XML documents can be parsed and generated.

The wsdl2h tool performs the mapping of WSDL and XML schemas to C and/or C++ automatically. The output of wsdl2h is a "data binding interface file" which is simply an annotated C/C++ header file with the serializable C/C++ data types that represent XML schema components. This file also includes comments and documentation of the serializable data types. For WSDLs, also functions are declared in this interface file that represent XML Web services operations.

Let's illustrate XML data bindings with an example. Suppose we have an XML document with a book record:

<book isbn="1234567890">
<title>Farewell John Doe</title>
<publisher>ABC's is our Name</publisher>
</book>

An example XML schema (XSD file) that defines the book element and type could be:

<schema ...>
<element name="book">
<complexType>
<sequence>
<element name="title" type="string" minOccurs="1"/>
<element name="publisher" type="string" minOccurs="1"/>
</sequence>
<attribute name="isbn" type="unsignedLong" use="required"/>
</complexType>
</element>
</schema>

Now, using wsdl2h we translate this XML schema that defines the book type and root element into a C++ class definition:

class book
{ public:
@ ULONG64 isbn;
std::string title;
std::string publisher;
};
#define ULONG64
User-definable macro that represents a portable unsigned 64 bit integer type.
Definition stdsoap2.h:1378

Note that annotations such as @ are used to distinguish attributes from elements. These annotations are gSOAP-specific and are handled by the soapcpp2 tool that reads this generated interface file and generates the XML data binding implementation with serializers for the data types declared in the interface file.

That is, the soapcpp2 tool generates all the necessary code to parse and generate XML for book objects. Validation constraints such as minOccurs="1" and use="required" are included in the generated code as checks that are enforced with the #SOAP_XML_STRICT flag.

To write the XML representation of a book object instantiated in our C++ application, we first create a soap engine context and use it with soap_write_book (a function generated by soapcpp2) to write the object in XML to standard output:

struct soap *soap = soap_new1(SOAP_XML_INDENT); // new context
book bk;
bk.isbn = 1234567890;
bk.title = "Farewell John Doe";
bk.publisher = "ABC's is our Name";
if (soap_write_book(soap, &bk) != SOAP_OK)
... // error
soap_destroy(soap); // delete managed class instances
soap_end(soap); // delete managed data and temporaries
soap_free(soap); // finalize and free the context

The soap context holds the engine state and run-time flags, such as #SOAP_XML_INDENT, serialization options, and other I/O settings. This means that we can simply set the output file descriptor int soap::sendfd or output stream std::ostream* soap::os of the context to redirect the content to a file or string. Also, when serializing a graph with #SOAP_XML_GRAPH rather than an XML tree, the XML output contains id-ref attributes to reference nodes in the XML graph, similar to the way SOAP encoding with multi-reference id-ref/href works, see Section How to use XML serializers to save and load application data for details.

To read the XML representation from standard input into a book class instance:

struct soap *soap = soap_new1(SOAP_XML_STRICT); // new context
book bk;
if (soap_read_book(soap, &bk) != SOAP_OK)
... // error
else
cout << bk.isbn << ", " << bk.title << ", " << bk.publisher << endl;
... // further use of bk
soap_destroy(soap); // delete managed class instances
soap_end(soap); // delete managed data and temporaries
soap_free(soap); // finalize and free the context
#define SOAP_XML_STRICT
soap_mode XML input flag value to enable strict XML validation of messages received
Definition stdsoap2.h:1925

Automatic built-in strict XML validation is enabled with #SOAP_XML_STRICT, which ensures that data members are present so we can safely print them in this example, thus ensuring consistency of data with the XML schema.

We can set the int soap::recvfd file descriptor or the std::istream* soap::is input stream to read from a file or string stream instead of stdin.

The soap_destroy and soap_end calls deallocate the deserialized data, so use these with care. Memory management is automatic in gSOAP to avoid leaks.

The above example uses a very simple example schema. The gSOAP toolkit handles all XML schema constructs defined by the XML schema standard. The toolkit is also able to serialize pointer-based C/C++ data structures, including cyclic graphs, structs/classes, unions, enums, containers, and even special data types such as struct tm. Therefore, the toolkit works in two directions: from WSDL/schema to C/C++ and from C/C++ to WSDL/schema.

The gSOAP toolkit also handles multiple schemas defined in multiple namespaces. Normally the namespace prefixes of XML namespaces are added to the C/C++ type definitions to ensure type uniqueness. For example, if we would combine two schemas in the same application where both schemas define a book object, we need to resolve this conflict. In gSOAP this is done using namespace prefixes, rather than C++ namespaces (research has pointed out that XML namespaces are not equivalent to C++ namespaces). Thus, the book class might actually be bound to an XML namespace and the class would be named ns__book, where ns is bound to the corresponding namespace.

For example, the following run-time flags are available to control serialization as an XML tree or graph:

struct soap *soap = soap_new();
soap_set_mode(soap, SOAP_XML_TREE); // use this for XML without id-ref (no cycles!)
soap_set_mode(soap, SOAP_XML_GRAPH); // or use this for XML with id-ref (including cycles)
*Set input and output ::soap_mode flags of the given ::soap context void soap_set_mode(struct soap *soap, soap_mode input_and_output_mode)
#define SOAP_XML_TREE
soap_mode XML input/output flag value to serialize C/C++ data structures as XML trees without id-href...
Definition stdsoap2.h:2118
#define SOAP_XML_GRAPH
soap_mode XML input/output flag value to serialize C/C++ (cyclic) data structures in XML with id-ref ...
Definition stdsoap2.h:2137

Other flags can be used to format XML, see Section Run-time flags .

For more details on XML databinding support for C and C++, see Section How to use XML serializers to save and load application data and the C and C++ XML data bindings document.

🔝 "" "Back to table of contents"

A quick user guide

This section of the user guide presents a quick overview to get started with gSOAP. In principle, XML SOAP and REST clients and services can be developed in C and C++ with the soapcpp2 tool without a detailed understanding of XML, XML schema, WSDL, and the XML SOAP protocol.

🔝 "" "Back to table of contents"

How to build Web API clients

The implementation of a client application that invokes remote service operations by serializing application data in XML for the remote operation request, also called XML marshalling in remote procedure calling. This requires a "stub function", also called "service proxy", for each service operation that the client invokes. The primary stub's responsibility is to serialize the parameter data in XML, send the request with the parameters to the designated SOAP service over the wire, to wait for the response, and to deserialize the parameter data of the response when it arrives. With the stub function in place, the client application invokes a remote service operation as if it would invoke a local function. To write a client stub function in C or C++ by hand is a tedious task, especially if the input and output parameters of a service operation contain elaborate data structures that must meet XML validation constraints. Fortunately, the wsdl2h tool and soapcpp2 tool automate the development of SOAP/XML Web service client and server applications.

The soapcpp2 tool generates the necessary gluing code (the client stub functions and server skeleton functions) to build web service clients and services. The input to the soapcpp2 tool consists of an interface file with familiar C/C++ header file syntax. This interface header file can be automatically generated from a WSDL (Web Service Description Language) documentation of a service with the gSOAP wsdl2h tool.

The following command:

 wsdl2h -o calc.h http://www.genivia.com/calc.wsdl

generates the calc.h interface header file for soapcpp2. The WSDL specification may consist of multiple imported WSDL files and XSD schema files. The WSDLs and XSDs are then translated to C or C++, replacing WSDL service operation by C/C++ functions and XML schema data types by C/C++ data types.

To generate C code, we use `wsdl2h -c` option `-c`:

 wsdl2h -c -o calc.h http://www.genivia.com/calc.wsdl

For more details on the wsdl2h tool and its options, see Section The wsdl2h tool .

When upgrading gSOAP to a newer version it is often not necessary to perform this first step again, since newer versions are backward compatible to previous interface header files generated by wsdl2h.

Looking into the file calc.h we see that the SOAP service methods are specified as function prototypes. For example, the add function to add two doubles is declared as:

int ns2__add(double a, double b, double& result);

The ns2__add function uses an XML namespace prefix to distinguish it from operations defined in other namespaces, thus nicely preventing name clashes in this way. The convention to add an XML namespace prefix to the names of operations, types, and struct and class members is universally used by the gSOAP tools and automatically added by wsdl2h.

Next, the calc.h header file is input to the soapcpp2 tool to generate the gluing code's logic to invoke the Web service from a client application:

soapcpp2 calc.h

The function prototypes in calc.h are converted by the soapcpp2 tool to stub functions for remote calls:

  • soapStub.h annotated copy of the header file's definitions.
  • soapH.h XML serializers declarations
  • soapC.cpp XML serializers implementations
  • soapClient.cpp the client calling stub functions

The logic of the generated soapClient.cpp stub functions allow client applications to seamlessly interact with existing SOAP Web services as illustrated by the client code example in the next section.

The input and output parameters of a service operation may be primitive data types or compound data types, such as containers and pointer-based linked data structures. These are defined in the interface header file, which is either generated by the wsdl2h tool or it may be specified by hand. The soapcpp2 tool automatically generates XML serializers and XML deserializers for these data types to enable the generated stub functions to serialize the contents of the parameters of the service operations in XML.

The soapcpp2 tool also generates "skeleton functions" soapServer.cpp for each of the service operations specified in the interface header file. The skeleton functions can be readily used to implement one or more of the service operations in a new XML Web service.

To develop C++ client applications, a useful option to use with soapcpp2 is -j to generate proxy classes to invoke services, instead of global functions:

soapcpp2 -j calc.h

The function prototypes in calc.h are converted by the soapcpp2 tool to the following function:

  • soapStub.h annotated copy of the header file's definitions.
  • soapH.h XML serializers declarations
  • soapC.cpp XML serializers implementations
  • soapcalcProxy.h the client proxy class
  • soapcalcProxy.cpp the client proxy class implementation

To use the proxy class, #include "soapcalcProxy.h" and compile and link soapcalcProxy.cpp. See the following section.

🔝 "" "Back to table of contents"

Example

The add service operation declared in the calc.h file obtained with the wsdl2h tool in the previous section, adds two doubles. The WSDL description of the service provides the endpoint to invoke the service operations and the XML namespace used by the operations:

Each SOAP-specific service operation also has a "SOAP action", which is an optional string to identify the operation, which is mainly used with WS-Addressing. The request and response messages for SOAP RPC-encoded services are simply represented by C functions with input and output parameters. For the add operation, the SOAP binding details are:

  • SOAP style: RPC
  • SOAP encoding: encoded
  • SOAP action: ""

This information is translated to the wsdl2h-generated interface header file with the service definitions. The calc.h header file for C++ generated by wsdl2h contains the following directives and declarations:

//gsoap ns2 schema namespace: urn:calc
//gsoap ns2 schema form: unqualified
//gsoap ns2 service name: calc
//gsoap ns2 service type: calcPortType
//gsoap ns2 service port: http://example.com/service.cgi
//gsoap ns2 service namespace: urn:calc
//gsoap ns2 service transport: http://schemas.xmlsoap.org/soap/http
//gsoap ns2 service method-protocol: add SOAP
//gsoap ns2 service method-style: add rpc
//gsoap ns2 service method-encoding: add http://schemas.xmlsoap.org/soap/encoding/
//gsoap ns2 service method-action: add ""
int ns2__add(double a, double b, double& result);

The actual contents may vary depending on the release version and the options used to control the output.

The other calculator service operations are similar and were elided for clarity.

The //gsoap directives are interpreted by the soapcpp2 tool to generate code that is compliant to the SOAP protocol. For this service the SOAP protocol with the "SOAP 1.1 RPC encoding style" is used. This produces XML messages with the familiar SOAP envelope and body in the SOAP 1.1 namespace and a SOAP-ENV:encodingStyle attribute for SOAP RPC encoding (a simple XML serialization format) as can be seen in the XML request message:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns="http://tempuri.org/ns.xsd">
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/>
<ns:add>
<a>1.0</a>
<b>2.0</b>
</ns:add>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Another style is "document/literal" which is also defined by SOAP 1.1/1.2.

To use SOAP document/literal style is indicated for each service operation as follows in the interface file specification, which also switches to the SOAP 1.2 protocol:

//gsoap ns2 service method-protocol: add SOAP1.2
//gsoap ns2 service method-style: add document
//gsoap ns2 service method-encoding: add literal
//gsoap ns2 service method-action: add ""
int ns2__add(double a, double b, double& result);

This produces XML messages with the familiar SOAP envelope and body with the SOAP 1.2 namespace and without the encodingStyle attribute as can be seen in the XML request message:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns="urn:calc">
<SOAP-ENV:Body>
<ns:add>
<a>1.0</a>
<b>2.0</b>
</ns:add>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

REST instead of SOAP is specified with HTTP instead of SOAP with the //gsoap <prefix> service method-protocol: directive to carry our XML messages using the HTTP POST method without a SOAP envelope:

//gsoap ns2 service method-protocol: add HTTP
int ns2__add(double a, double b, double& result);

This produces non-SOAP XML messages with HTTP POST. For example:

<?xml version="1.0" encoding="UTF-8"?>
<ns:add
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns="urn:calc">
<a>1.0</a>
<b>2.0</b>
</ns:add>

Likewise you can specify POST, PUT, and GET HTTP methods for direct XML messaging instead of SOAP. However, all XML Web services protocols such as WS-Security and WS-Addressing require SOAP to include the SOAP Headers.

Note that the function declaration itself and the client-side calling stub and server-side skeleton functions are unchanged. The internals of the generated functions are changed to accommodate the protocol specified with the directives.

For more details about the //gsoap directives, see Section Directives .

So as you can see, the Web service operations are declared as function prototypes. When the parameters of the function are structs and classes, then all of these interdependent data types are included in the wsdl2h-generated header file.

In this simple example the parameters are primitive types. The calculator add operation takes two double floats a and b, and returns the sum in result. By convention, all parameters are input parameters except the last parameter which is an output parameter or specified as void for one-way messages. The last parameter is always a single output parameter, if not void. A struct or class is used to wrap multiple output parameters, see also Section How to specify multiple output parameters . This last parameter must be a pointer or reference. By contrast, the input parameters support pass by value or by pointer, but not pass by C++ reference due to complications when generating compilable source code for the stub and skeleton functions.

The function prototype associated with a service operation always returns an int. The return value indicates success with #SOAP_OK (zero) or failure with a nonzero value. See Section Run-time error codes for the error codes.

The role of the namespace prefix (ns2__) in the service operation name specified as a function prototype associates an XML namespace with the service operation as a qualified name, i.e. qualified by means of a namespace prefix. This is discussed in detail in Section XML namespace considerations . Basically, the namespace prefix is added to a function name or type name with a pair of underscores, as in ns2__add, where ns2 is the namespace prefix and add is the service operation name. This mechanism ensures uniqueness of operations and types associated with a service.

When using wsdl2h it is strongly recommended to set the namespace prefix to a name of your choice by modifying the typemap.dat file that is used by wsdl2h. This file can be copied from gsoap/typemap.dat and modified in the local directory where you run wsdl2h. This avoids problems when running wsdl2h on multiple WSDLs where the sequence of prefixes ns1, ns2, and so on are arbitrarily assigned to the services. To choose a prefix name for all the operations and types of a service, say prefix c__ for the calculator service, add the following line to typemap.dat:

c = "urn:calc"

and rerun wsdl2h. Moreover, the typemap.dat configures wsdl2h to use specific bindings and data types for services. The result is that c__add is used to uniquely identify the operation rather than the more arbitrary name ns2__add.

A note on the use of underscores in names: a single underscore in an identifier name will be translated into a dash in XML, because dashes are more frequently used in XML compared to underscores, see Section C/C++ identifier name to XML tag name translation . Double underscores separate the namespace prefix from the unqualified part of the qualified name.

Next, the soapcpp2 tool is invoked from the command line to process the calc.h service definitions:

 soapcpp2 calc.h

The tool generates the client stub functions for the service operations. Stub functions can be invoked by a client program to invoke the remote service operations. The interface of the generated stub function is identical to the function prototype in the calc.h service definition file, but with additional parameters to pass the engine's context soap, an endpoint URL (or NULL for the default), and a SOAP action (or NULL for the default):

int soap_call_c__add(struct soap *soap, char *URL, char *action, double a, double b, double& result);

This stub function is saved in soapClient.cpp. The file soapC.cpp contains the serializer and deserializer functions for the data types used by the stub. You can use `wsdl2h -c` option `-c` to generate pure C code. Likewise, soapcpp2 -c option -c generates pure C code, if the input interface file is written in C of course.

The soap parameter of the stub function shown above must be a valid pointer to a soap context. The URL parameter when non-NULL overrides the default endpoint address defined by the WSDL and the //gsoap <prefix> service port: directive. The action parameter when non-NULL overrides the default SOAP action defined by the WSDL and the //gsoap <prefix> service method-action: directive.

The following example C/C++ client program uses the generated stub function to invoke the remote service operation:

#include "soapH.h" // include the generated declarations
#include "calc.nsmap" // include the generated namespace table
int main()
{
double sum;
struct soap *soap = soap_new(); // the context
if (soap_call_c__add(soap, NULL, NULL, 1.0, 2.0, &sum) == SOAP_OK)
std::cout << "Sum = " << sum << std::endl;
else // an error occurred
soap_print_fault(soap, stderr); // display the SOAP fault message on the stderr stream
soap_destroy(soap); // delete managed class instances
soap_end(soap); // delete managed data and temporaries
soap_free(soap); // finalize and free the context
return 0;
}

The soap_call_c__add call returns #SOAP_OK (zero) on success and a nonzero error on failure. When an error occurred you can print the fault message with the soap_print_fault(struct soap*, FILE*) function. Use soap_sprint_fault(struct soap*, char *buf, size_t len) to save the fault message to a string buffer buf[0...len-1]. Use soap_stream_fault(struct soap*, std::ostream&) to send the fault message to a stream.

The following functions are used to explicitly set up a soap context and finalize it:

  • soap_new() allocates, initializes, and returns a pointer to a new soap context.
  • soap_new1(soap_mode mode) allocates, initializes and sets both in- and out-mode flags to the same mode, and returns a pointer to a new soap context.
  • soap_new2(soap_mode imode, soap_mode omode) allocates, initializes and sets in- and out-mode flags, and returns a pointer to a new soap context.
  • soap_copy(struct soap*) allocates and returns a new context by copying the given context with soap_copy_context, such that the new context returned does not share any data with the given context.
  • soap_init(struct soap*) initializes a stack-allocated soap context in C, when not using ::soap_new, for C++ use the soap constructors instead.
  • soap_init1(struct soap*, soap_mode mode) initializes a stack-allocated soap context, when not using ::soap_new1, and sets both in- and out-mode flags to the same mode, for C++ use the soap constructors instead.
  • soap_init2(struct soap*, soap_mode imode, soap_mode omode) initializes a stack-allocated soap context, when not using ::soap_new2, and sets in- and out-mode flags, for C++ use the soap constructors instead.
  • soap_done(struct soap*) finalizes a context but does not delete the specified soap context (for example when stack-allocated). The context can be re-initialized afterwards with soap_init. In C++, a stack-allocated context invokes this function in its destructor when the context is deleted.
  • soap_free(struct soap*) finalizes and deletes the given context, when created with ::soap_new or ::soap_copy.

A soap context can be reused as many times as necessary and does not need to be reinitialized when doing so. However, a new context is required for each thread that runs independently to guarantee exclusive access to a soap context by each thread.

Also the use of any client calls within an active service operation implemented at the server side requires a new context, since soap_serve is still processing with the current soap context that must be maintained while the service operation and response has not been completed yet.

The soapcpp2 code generator tool generates a service proxy class for C++ client applications (and service objects for server applications) with the soapcpp2 -j option -j (or -i option):

 soapcpp2 -j calc.h

The proxy is defined in:

  • soapcalcProxy.h client proxy class
  • soapcalcProxy.cpp client proxy class

Without the -j option, C-like soapClient.cpp and soapServer.cpp source codes are is generated. Use option -i as an alternative to -j to generate classes with the same functionality, but that are inherited from the soap struct. With the -j option, the soap engine context is a pointer member of the generated proxy and service classes and can therefore be shared with other proxy or service class instances. The choice of option to use is application-dependent, but the choice is also important when services are chained to serve requests on the same server port, see Section How to chain C++ server classes to accept messages on the same port .

The generated C++ proxy class initializes the context and offers the service interface as a collection of methods:

#include "soapcalcProxy.h" // get proxy
#include "calc.nsmap" // include the generated namespace table
int main()
{
calcProxy calc(SOAP_XML_INDENT);
double sum;
if (calc.add(1.0, 2.0, sum) == SOAP_OK)
std::cout << "Sum = " << sum << std::endl;
else
calc.soap_stream_fault(std::cerr);
calc.destroy();
return calc.soap->error; // nonzero when error
}

The proxy constructor takes context mode parameters to initialize the context, e.g. #SOAP_XML_INDENT in this example.

The code is compiled and linked with soapcalcProxy.cpp, soapC.cpp, and gsoap/stdsoap2.cpp.

The proxy class name is extracted from the WSDL content and may not always be in a short format. You can change this directive to customize the service name:

//gsoap c service name: calc

then rerun soapcpp2 to generate code that uses the new name.

When the example client application is invoked, a SOAP request is performed:

POST /~engelen/calcserver.cgi HTTP/1.1 
Host: websrv.cs.fsu.edu 
User-Agent: gSOAP/2.8 
Content-Type: text/xml; charset=utf-8 
Content-Length: 464 
Connection: close 
SOAPAction: "" 
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:c="urn:calc">
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<c:add>
<a>1</a>
<b>2</b>
</c:add>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The SOAP response message is:

HTTP/1.1 200 OK 
Date: Wed, 05 May 2010 16:02:21 GMT 
Server: Apache/2.0.52 (Scientific Linux) 
Content-Length: 463 
Connection: close 
Content-Type: text/xml; charset=utf-8 
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns="urn:calc">
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<ns:addResponse>
<result>3</result>
</ns:addResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

A client can invoke a sequence of service operations, like so:

#include "soapcalcProxy.h" // get proxy
#include "calc.nsmap" // include the generated namespace table
int main()
{
calcProxy calc(SOAP_IO_KEEPALIVE); // keep-alive improves connection performance
double sum = 0.0;
double val[] = { 5.0, 3.5, 7.1, 1.2 };
for (int i = 0; i < 4; i++)
if (calc.add(sum, val[i], sum))
return calc.soap->error;
std::cout << "Sum = " << sum << std::endl;
calc.destroy();
return 0;
}
#define SOAP_IO_KEEPALIVE
soap_mode IO input and output flag value to keep the socket connection alive for #SOAP_MAXKEEPALIVE m...
Definition stdsoap2.h:1732

In the example shown above, no deserialized data is deallocated until calc.destroy(). To deallocate deserialized data between the calls we change the loop as follows:

for (int i = 0; i < 4; i++)
{
if (calc.add(sum, val[i], sum))
return calc.soap->error;
calc.destroy();
}

Deallocation is safe here, since the float values were copied and saved in sum. In other scenarios we should make sure data is copied to local data structures when the data should be preserved. There are tooling options for deep copy and delete of entire data structures to simplify this task, see Section Generating deep copy and deletion functions.

To delegate deletion to another context for later removal, use soap_delegate_deletion(struct soap *soap_from, struct soap *soap_to). For example:

struct soap soap;
{
// create proxy
calcProxy calc;
... // data produced, e.g. deserialized data with client-side calls
calc.destroy();
}
... // data can still be used
soap_destroy(&soap); // delete managed class instances
soap_end(&soap); // delete managed data and temporaries
soap_done(&soap); // finalize the context
*Allocate and initialize a new ::soap context struct soap *soap_new *() * @returns pointer to allocated and initialized ` Allocate and initialize a new ::soap context with input and output ::soap_mode flags struct soap *soap_new1 *(soap_mode input_and_output_mode) * @returns pointer to allocated and initialized ` Allocate and initialize a new ::soap context with separate input and output ::soap_mode flags struct soap *soap_new2 *(soap_mode input_mode, soap_mode output_mode) * @returns pointer to allocated and initialized ` Initialize a stack allocated ::soap context void soap_init(struct soap *soap)
*Delegate the deletion of all managed objects and data from the specified ::soap context to another ::soap context void soap_delegate_deletion(struct soap *soap, struct soap *soap_to)
*Finalize the given ::soap i e when the ::soap context is stack automatically invoked in C by the ::soap destructor on the ::soap context to delete void soap_done(struct soap *soap)

In C we use `wsdl2h -c` option `-c`