Simple calculator service implements:

   add(a,b)
   sub(a,b)
   mul(a,b)
   div(a,b)
   pow(a,b)

Compilation in C (see samples/calc):
    soapcpp2 -c calc.h
    cc -o calcclient calcclient.c stdsoap2.c soapC.c soapClient.c
    cc -o calcserver calcserver.c stdsoap2.c soapC.c soapServer.c
  As a concurrent multithreaded server:
    cc -DMULTITHREADED -o calcserver calcserver.c stdsoap2.c soapC.c soapServer.c -lpthread
  As a concurrent multithreaded server with HTTPS SSL/TLS (requires server.pem):
    cc -DWITH_OPENSSL -DMULTITHREADED -o calcserver calcserver.c stdsoap2.c soapC.c soapServer.c -lpthread -lssl -lcrypto

Compilation in C++ (see samples/calc++):
    soapcpp2 -i calc.h
    c++ -o calcclient++ calcclient.cpp stdsoap2.cpp soapC.cpp soapcalcProxy.cpp
    c++ -o calcserver++ calcserver.cpp stdsoap2.cpp soapC.cpp soapcalcService.cpp
  As a concurrent multithreaded server:
    c++ -DMULTITHREADED -o calcserver++ calcserver.cpp stdsoap2.cpp soapC.cpp soapcalcService.cpp -lpthread
  As a concurrent multithreaded server with HTTPS SSL/TLS (requires server.pem):
    c++ -DWITH_OPENSSL -DMULTITHREADED -o calcserver++ calcserver.cpp stdsoap2.cpp soapC.cpp soapcalcService.cppc -lpthread -lssl -lcrypto

For C++ development soapcpp2 option -i generates proxy and service classes,
which encapsulate the method operations in the class instead of defining them
as global functions as in C.

The calcclient application invokes the service and is used from the command
line as follows:

$ calcclient add 3 4
result = 7

The calcserver application is a CGI application that can be installed under the
cgibin of your Web server.

The C client-side uses:

  Initialization of the runtime engine:
    soap_init(struct soap*)
  Invoking a call of xyz, this function is generated by soapcpp2:
    soap_call_ns__xyz(struct soap*, const char *endpoint, const char *action,
                      double a, double b, double *result)
    Note: endpoint=NULL and action=NULL for defaults
  Print communication errors:
    soap_print_fault(struct soap*, FILE*)
  Allocate data, which stays alive until deallocated by soap_end()
    soap_malloc(struct soap*, size_t len)
  Delete deserialized data:
    soap_end(struct soap*)
  Finalize and detach the runtime engine:
    soap_done(struct soap*)

The C server-side uses:

  Initialization of the runtime engine:
    soap_init(struct soap*)
  Binding the port:
    soap_bind(struct soap*, const char *host, int port, int backlog)
  Accepting a request:
    soap_accept(struct soap*);
  Invoking the service dispatcher, this function is generated by soapcpp2:
    soap_serve(struct soap*)
  Print communication errors:
    soap_print_fault(struct soap*, FILE*)
  Allocate data, which stays alive until deallocated by soap_end()
    soap_malloc(struct soap*, size_t len)
  Delete deserialized data:
    soap_end(struct soap*)
  Send back sender-related fault:
    soap_sender_fault(struct soap*, const char *string, const char *detailXML)
  Send back receiver-related fault:
    soap_receiver_fault(struct soap*, const char *string, const char *detailXML)
  Finalize and detach the runtime engine:
    soap_done(struct soap*)
  Service operations are not auto-generated (user-defined):
    ns__add(struct soap*, double a, double b, double *result)
    ns__sub(struct soap*, double a, double b, double *result)
    ns__mul(struct soap*, double a, double b, double *result)
    ns__div(struct soap*, double a, double b, double *result)
    ns__pow(struct soap*, double a, double b, double *result)

The C++ client-side uses a proxy generated with soapcpp2 -i: class calcProxy

  The default endpoint can be changed:
    const char *calcProxxy::endpoint
  Invoke a call of xyz:
    calcProxy::xyz(double a, double b, double *result)
  Print communication errors:
    calcProxy::soap_stream_fault(std::ostream&)
  Error code (see list of error codes in documentation and stdsoap2.h):
    calcProxy::error
  Allocate data, deallocated by soap_end() or calcProxy destructor
    soap_malloc(calcProxy*, size_t len)
  Get new instance of class X, deallocated by soap_destroy() or calcProxy destructor
    soap_new_X(calcProxy*, -1)
  Get array of new instances of class X, deallocated by soap_destroy() or calcProxy destructor
    soap_new_X(calcProxy*, arraylen)
  Delete deserialized C++ class instances (also part of calcProxy destructor):
    soap_destroy(calcProxy*)
  Delete deserialized data (also part of calcProxy destructor):
    soap_end(calcProxy*)

The C++ server-side uses a class generated with soapcpp2 -i: class calcService

  Serve requests over stdin/out (for CGI)
    calcService::serve()
  Serve multiple requests over port (iterative HTTP server):
    calcService::run()
  Print communication errors:
    calcService::soap_stream_fault(std::ostream&)
  Error code (see list of error codes in documentation and stdsoap2.h):
    calcService::error
  Send back sender-related fault:
    calcService::soap_senderfault(const char *string, const char *detailXML)
  Send back sender-related fault with subcode (SOAP 1.2):
    calcService::soap_senderfault(const char *subcodeQName, const char *string, const char *detailXML)
  Send back receiver-related fault:
    calcService::soap_receiver_fault(const char *string, const char *detailXML)
  Send back receiver-related fault with subcode (SOAP 1.2):
    calcService::soap_receiver_fault(const char *subcodeQName, const char *string, const char *detailXML)
  Service operations are user-defined (not auto-generated):
    calcService::add(double a, double b, double *result)
    calcService::sub(double a, double b, double *result)
    calcService::mul(double a, double b, double *result)
    calcService::div(double a, double b, double *result)
    calcService::pow(double a, double b, double *result)
  Allocate data, deallocated by soap_end() or calcService destructor
    soap_malloc(calcService*, size_t len)
  Get new instance of class X, deallocated by soap_destroy() or calcService destructor
    soap_new_X(calcService*, -1)
  Get array of new instances of class X, deallocated by soap_destroy() or calcService destructor
    soap_new_X(calcService*, arraylen)
  Delete deserialized C++ class instances (also part of calcService destructor):
    soap_destroy(calcService*)
  Delete deserialized data (also part of calcService destructor):
    soap_end(calcService*)

Note: all soap_xyz(struct soap*, ...) gSOAP API functions are also available
to the calcProxy and calcService classes by inheritance of the struct soap
runtime engine state object.
