c - gSoap generated client-side structure initialization and use -
gsoap generated client-side structure initialization , use (using ansi c bindings)
first of all, searched , although there number of struct initialization solutions offered, did not find directly answering issue.
also, question being posted assist else has similar question, i have worked out solution , because of newbie status
post immediatelyat least 8 hours
after posting this.
however, still interested in comments , edits solution offer better solutions, or more experience in gsoap...
the scenario:
new soap in general, , have been using gsoap generated client source code build ansi c bindings access web services. arguments 4 & 5 of "soap_call__" functions provided application interfaces (defined within soapclient.c) many times complex (nested) structures. argument 4 specifically, because it input structure, has declared, initialized, allocated , freed within calling application.
for example, given 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 following structure definition (looking @ argument 4) defined in soapstub.h
(note: have shortened names , reduced number of members original contents of structures 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 members , pointers within complex (nested) input structure initialized, memory allocated, values assigned , memory freed such useable within calling application?
originally posted address structures generated gsoap utilities specifically, has general applicability nested struct pointers...
addresses question of initializing, allocating, assigning , freeing members , pointers within nested structure construct ansi c.
to explain shape of structs requiring treatment, data schema comprised of known number of header fields, each having 1 value per row followed delimiter ********, followed unknown number of data fields, each having known (and constant) number of comma delimited fields:
example data:
the 2 files shown below commented. together, compile , build ansi c compiler:
initcomplexstructs.h:
//the struct names typical in gsoap generated code //are longer , more complicated. //for example, typical client soap_call___ns...() //function prototype may this: //soap_fmac5 int soap_fmac6 soap_call___ns1__sendledf(struct soap *soap, const char *soap_endpoint, const char *soap_action, struct _ns3__ledf_send *ns3__xxmtsvclws, struct _ns3__ledf_recv *ns3__xxmtsvclwsresponse) //where areguments 4 & 5 respectively: // arg 4: struct _ns3__ledf_send *ns3__xxmtsvclws // arg 5: struct _ns3__ledf_recv *ns3__xxmtsvclwsresponse // //for project assume arg 4 represents complex (nested) //set of data structures, , illustration purposes, shorten //name aaa: // struct aaa contains members accomodate fixed number of strings // pointer struct bbb struct aaa { char *aaastr1; char *aaastr2; char *aaastr3; char *aaastr4; char *aaastr5; struct bbb *pbbb; }; // struct bbb used set array order size // (or number of copies necessary of struct ccc) // contains array size (index value) member "numrows" // , pointer struct, work pointer // array of struct ccc struct bbb { int numrows; struct ccc *row; }; // struct ccc contains members accomodate variable number of // sets of strings, number of sets determined array row[] // initialized array size "numrows" in struct bbb // (see initcomplexstructs.c how done) struct ccc { char *cccstr1; char *cccstr2; char *cccstr3; char *cccstr4; char *cccstr5; };
initcomplexstructs.c
/////////////////////////////////////////////////////////// ///// using nested data structures //////////////////////// /////////////////////////////////////////////////////////// // // client-side gsoap generated code use nested // data structures accomodate complex data types // used in 4th , 5th arguments of client // soap_call__ns...() functions. // // program illustrates how work these // structures calling application in // following way : // // - initialization of structs // - allocation of structs , members // - assignment of values members // - freeing of allocated memory // /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// #include <ansi_c.h> #include "initcomplexstructs.h" struct aaa _aaa, *p_aaa; struct bbb _bbb, *p_bbb; struct ccc _row, *p_row; void initializestructs(void); void allocatestructs(void); void assignstructs(void); void freestructs(void); char typicalstr[]={"aaastr 1"}; size_t sizestr = sizeof(typicalstr); void main (void) { initializestructs(); allocatestructs(); assignstructs(); freestructs(); } void initializestructs(void) { p_aaa = &_aaa; p_bbb = &_bbb; p_row = &_row; } void allocatestructs(void) { int i; //allocate members of p_aaa p_aaa->aaastr1 = calloc(sizestr, sizeof(char)); p_aaa->aaastr2 = calloc(sizestr, sizeof(char)); p_aaa->aaastr3 = calloc(sizestr, sizeof(char)); p_aaa->aaastr4 = calloc(sizestr, sizeof(char)); p_aaa->aaastr5 = calloc(sizestr, sizeof(char)); p_aaa->pbbb = malloc( sizeof(*p_bbb)); //allocate member of next nested struct - pbbb //note: order of array determined //by value assigned "numrows" //note also: value numrows passed in argument //since calling function has information. //just requires prototype mod void int argument. p_aaa->pbbb->numrows = 3; p_aaa->pbbb->row = calloc(p_aaa->pbbb->numrows,sizeof(*p_row)); //allocate innermost struct ccc accessed through *row for(i=0;i<p_aaa->pbbb->numrows;i++) { p_aaa->pbbb->row[i].cccstr1 = calloc(sizestr, sizeof(char)); p_aaa->pbbb->row[i].cccstr2 = calloc(sizestr, sizeof(char)); p_aaa->pbbb->row[i].cccstr3 = calloc(sizestr, sizeof(char)); p_aaa->pbbb->row[i].cccstr4 = calloc(sizestr, sizeof(char)); p_aaa->pbbb->row[i].cccstr5 = calloc(sizestr, sizeof(char)); } } void assignstructs(void) { int i; strcpy(p_aaa->aaastr1, "aaastr 1"); strcpy(p_aaa->aaastr1, "aaastr 2"); strcpy(p_aaa->aaastr1, "aaastr 3"); strcpy(p_aaa->aaastr1, "aaastr 4"); strcpy(p_aaa->aaastr1, "aaastr 5"); for(i=0;i<p_aaa->pbbb->numrows;i++) { strcpy(p_aaa->pbbb->row[i].cccstr1, "bbbstr 1"); strcpy(p_aaa->pbbb->row[i].cccstr2, "bbbstr 2"); strcpy(p_aaa->pbbb->row[i].cccstr3, "bbbstr 3"); strcpy(p_aaa->pbbb->row[i].cccstr4, "bbbstr 4"); strcpy(p_aaa->pbbb->row[i].cccstr5, "bbbstr 5"); } } void freestructs(void) { int i; for(i=0;i<p_aaa->pbbb->numrows;i++) { free(p_aaa->pbbb->row[i].cccstr1); free(p_aaa->pbbb->row[i].cccstr2); free(p_aaa->pbbb->row[i].cccstr3); free(p_aaa->pbbb->row[i].cccstr4); free(p_aaa->pbbb->row[i].cccstr5); } free(p_aaa->pbbb->row); free(p_aaa->pbbb); free(p_aaa->aaastr1); free(p_aaa->aaastr2); free(p_aaa->aaastr3); free(p_aaa->aaastr4); free(p_aaa->aaastr5); }
Comments
Post a Comment