Using gsoap for web services
This article explains how to work with gsoap on Symbian - a cross-platform open source C and C++ software development toolkit that generates C/C++ RPC code, XML data bindings, and efficient schema-specific parsers for SOAP Web services.
With the time-to-market being so critical for mobile applications, One would certainly like to have as much reusable components as possible. This is where generic components come into picture.
Let us say you want to design a S60 application with SOAP/XML web services communication. Nokia provides a WSDL-to-C++ tool to generate stubs from wsdl file and Xmldatabinding libraryto run this code. However, later if you decide to port this application to UIQ( or even Samsung S60 devices), you need to re-design your application as this library is provided by Nokia and doesn't work on other platforms or even S60 devices from other manufacturers. How to avoid this problem by making the SOAP communication generic for all platforms. The answer is gsoap.
What is gSOAP
A cross-platform open source C and C++ software development toolkit. Generates C/C++ RPC code, XML data bindings, and efficient schema-specific parsers for SOAP Web services.
The primary reason to go for gSOAPis portability.gSOAP supports most platforms, including embedded systems and small OS (for example WinCE, Symbian, and PalmOS).
How to use gSOAP
Download the latest gSOAP package from the SourceForge gSOAP project site. The gSOAP distribution package includes two compiler tools to develop your applications:
'wsdl2h' WSDL parser: This tool converts WSDLs and XSD files into annotated C/C++ definitions.
'soapcpp2' stub and skeleton compiler :This tool generates RPC code and XML serializers from the annotated C/C++ definitions.
The 'wsdl2h' parser converts WSDL into gSOAP header file specifications of Web services. This specification gives a C/C++ transparent view of the server's functionality. The header file is processed by 'soapcpp2' to generate the source code stubs and skeletons to invoke the service or build a new service based on the WSDL.
Binary files location in the unzipped package
After you unzip the downloaded package, you can view the binaries of above said two tools at the path: gsoap_2.8.3\gsoap-2.8\gsoap\bin\win32 (in Windows Environment).
Step1: Generating the header file
The first step is to generate the header file from your wsdl file using the wsdl2h tool. We may need to modify the typemap.dat file to include the namespaces corresponding to our wsdl. If the namespace is unspecified, the wsd2l tool will use the default ns1...ns2 values. In essence a namespace aims to provide unique means to identify a type.
- To run the following commands, you may need to open command prompt first and then reach to the directory where your binary files of the tools are placed. For Example, if your binaries are placed at the path D:\user\Symbian\gsoap_2.8.3\gsoap-2.8\gsoap\bin\win32
then first you have to reach to this directory in command prompt.
After you reach till the directory where your binaries are placed, you may exeute the following command
>wsdl2h -s -t typemap.dat -o soapProxy.h mywebservice.wsdl
-s indicates that code that relies on STL should not be generated since the STL is not available for Symbian.
-o specifies the output name of the file;
-t specifies the Specific typemap.dat to be used.
for more options, use wsdl2h -help
Suppose we want to process the calc.wsdl file placed at location http://www.yoirservername.com/calc.wsdl by our wsdl2h tool to generate calc.h header file. To do this, we will execute the following command
>wsdl2h -o calc.h http://www.yoirservername.com/calc.wsdl
On successful execution this command will generate a header file named calc.h at the same location where your binary files are placed.
Step2: Generating C++ code
We need to run the soapProxy.h through the gSOAP compiler in order to create the proxy, serializers and namespace mapping file.
The soapcpp2.exe is used with the following parameters:
soapcpp2 -t -C -L soapProxy.h
-t indicates that code is to generate typed messages (with the xsi:type attribute).This helps ensure interoperability and compatibility when using RPC-encoded style.
-C indicates that only client side code should be generated.
-L By default the compiler will attempt to create a soapClientLib.cpp which is relevant for building static or dynamic libraries. This is not relevant to us and is therefore disabled with the -L flag.
After we generated calc.h header file, we now need to generate the rest of the stub files. To do this, we will execute the command having following syntax
>soapcpp2 -i -C -I<path> calc.h
Here, path refers to the path of the file stlvector.h So, according to our example the command will be:
>soapcpp2 -i -C -ID:\user\Symbian\gsoap_2.8.3\gsoap-2.8\gsoap\import calc.h
After the successful execution of above command, we will be having some .h, .cpp and .xml type files at the same location where our binary files are placed.
Step3: Include generated file to your project directory
|soapProxy.h||Defines schema types, services & bindings||X|
|soapStub.h||Amended schema types, services & binding definitions||X|
|soapH.h||XML (de)serializers for data types||X|
|stdsoap2.h||The gSOAP runtime||X|
|myWebServiceSOAP11BindingProxy.h||Proxy to invoke the services||X|
|myWebServiceSOAP12BindingProxy.h||Proxy to invoke the services||X|
We need to add the directory \epoc32\include\libc in the mmp file like shown below:
Multithreading for non-blocking calls
To keep the application UI responsive, We can issue the gsoap call in a seperate thread.
TInt id = iThread2.Handle ();
if ( (id==KCurrentThreadHandle)||(id==0))
//Thread uses shared heap created within main thread
TInt err = iThread2.Create (_L("myupdater"),ThreadFunction,KDefaultStackSize,NULL,(TAny *)this);
if ( err==KErrNone)
// protected from CActive
TInt id = iThread2.Handle ();
if ( (id!=KCurrentThreadHandle)&&(id!=0))
/*Thread request must be indicated as completed
* when canceling the thread else the thread is blocked
* due to 'User::WaitForRequest()' in 'cancel()'
TRequestStatus* status = &iStatus;
if ( iStatus==KErrDied || KErrCancel)
//indicate the webservice response is processed - Ani
// private new methods
TInt CMyUpdater::ThreadFunction(TAny *aPtr)
CMyUpdater* ptr = (CMyUpdater*)aPtr;
// open main thread
thread.Open (ptr->iId, EOwnerProcess);
//Create a cleanup stack
CTrapCleanup* cleanup = CTrapCleanup::New ();
//Create and install a active scheduler
if ( !sched)
TRequestStatus* status = &(ptr->iStatus);
thread.RequestComplete (status, KErrDied);
//Delete the heap allocated stuff
//Issue web service request here and check for response