gSoap generated client-side structure initialization and use (using ANSI C bindings)
First of all, I searched and although there are a number of struct initialization solutions offered, I did not find anything directly answering this issue.
Also, this question is being posted simply to assist anyone else that has a similar question, as I have already worked out the solution and because of my newbie status
will post it immediatelyat least 8 hours
after posting this.
However, I am still very interested in comments and edits to the solution I will offer from those with better solutions, or with more experience in gSoap...
The Scenario:
I am fairly new to soap in general, and have been using gSoap generated client source code to build ANSI C bindings to access web services. Arguments 4 & 5 of the "soap_call__" functions provided as application interfaces (defined within soapClient.c) are many times complex (nested) structures. Argument 4 specifically, because it it is the input structure, has to be declared, initialized, allocated and freed within the calling application.
for example, given the following gSoap generated prototype:
SOAP_FMAC5 int SOAP_FMAC6 soap_call___ns1__SendFile((struct soap *soap, const char *soap_endpoint, const char *soap_action, struct ns3__send *mtdf, struct recv *response)
with the following structure definition (looking only at argument 4) defined in soapStub.h
(NOTE: I have shortened the names and reduced the number of members from original contents of the structures for illustrative purposes)
struct ns3__send
{
char *wsStDate; /* optional element of type xsd:date */
int *wsStDuration; /* optional element of type xsd:int */
int *wsStFailures; /* optional element of type xsd:int */
char *wsStFileName; /* optional element of type xsd:string */
struct ns3__Param *details; /* optional element of type ns3:Param */
};
struct ns3__Param
{
int __sizeRow; /* sequence of elements <wsStdDetailsRow> */
struct ns3__Row *row; /* optional element of type ns3:xxmtdfws_wsStdDetailsRow */
};
struct ns3__Row
{
int *wsStdSeq; /* optional element of type xsd:int */
char *wsStdStep; /* optional element of type xsd:string */
char *wsStdTestDesc; /* optional element of type xsd:string */
char *wsStdLowLim; /* optional element of type xsd:string */
};
The question is:
How are the members and pointers within this complex (nested) input structure properly initialized, memory allocated, values assigned and memory freed such that they are useable within a calling application?
The following describes an ANSI C method for initializing, allocating, assigning and freeing members and pointers within a nested structure construct where the number of fields in the nested section is unknown until run-time.
To explain the shape of structs requiring this treatment, The data schema is comprised of a known number of header fields, each field having one value per row. The last field (row) serves as a delimiter
********
between the header and data sections. The data section contains an unknown number of data records, but each record contains a known (and constant) number of comma delimited fields:Example data:
The two files shown below are fully commented. Together, they will compile and build with any ANSI C compiler:
InitComplexStructs.h:
InitComplexStructs.c
Are you aware that gSOAP allocates memory for your data structures for you so that you don't have to do this? You only have to allocate memory for any data in a Request structure, but never the a reply structure.