gSoap generó inicialización y uso de la estructura del lado del cliente

gSoap generó inicialización y uso de la estructura del lado del cliente (utilizando enlaces ANSI C)

En primer lugar, busqué y, aunque se ofrecen varias soluciones de inicialización de estructuras, no encontré nada que respondiera directamente a este problema.

Además, esta pregunta se está publicando simplemente para ayudar a cualquier otra persona que tenga una pregunta similar, ya que ya encontré la solución y, because of my newbie status , la publicaremos inmediatamente at least 8 hours después de publicar esta.

Sin embargo, todavía estoy muy interesado en los comentarios y ediciones a la solución que ofreceré de aquellos con mejores soluciones, o con más experiencia en gSoap …

El escenario:
En general, soy bastante nuevo en soap y he estado usando el código fuente generado por gSoap para crear enlaces ANSI C para acceder a los servicios web. Los argumentos 4 y 5 de las funciones “soap_call__” proporcionadas como interfaces de aplicación (definidas en soapClient.c) son muchas veces estructuras complejas (anidadas). El argumento 4 específicamente, porque es la estructura de entrada, debe declararse, inicializarse, asignarse y liberarse dentro de la aplicación que llama.

por ejemplo, dado el siguiente prototipo generado por gSoap:

 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) 

con la siguiente definición de estructura (mirando solo el argumento 4) definida en soapStub.h

(NOTA: he acortado los nombres y reducido el número de miembros de los contenidos originales de las estructuras con fines ilustrativos)

 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  */ 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 */ }; 

La pregunta es:

¿Cómo se inicializan correctamente los miembros y los punteros dentro de esta estructura de entrada compleja (anidada), la memoria asignada, los valores asignados y la memoria liberada de tal manera que se puedan utilizar dentro de una aplicación de llamada?

Originally posted to address structures generated by gsoap utilities specifically, but it has general applicability to any nested struct with pointers...

Aborda la cuestión de inicializar, asignar, asignar y liberar miembros y punteros dentro de una estructura de estructura anidada para ANSI C.

Para explicar la forma de las estructuras que requieren este tratamiento, el esquema de datos consta de un número conocido de campos de encabezado, cada uno con un valor por fila seguido de un delimitador ********, seguido de un número desconocido de datos campos, cada uno con un número conocido (y constante) de campos delimitados por comas:

Ejemplo de datos:
introduzca la descripción de la imagen aquí

Los dos archivos que se muestran a continuación están completamente comentados. Juntos, comstackrán y construirán con cualquier comstackdor ANSI C:

InitComplexStructs.h:

  //The struct names typical in gSoap generated code //are longer and more complicated. //for example, a typical client soap_call___ns...() //function prototype may look like 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 are respectively: // arg 4: struct _ns3__ledf_send *ns3__xxmtsvclws // arg 5: struct _ns3__ledf_recv *ns3__xxmtsvclwsResponse // //for this project we will assume arg 4 represents a complex (nested) //set of data structures, and for illustration purposes, shorten the //name to aaa: // struct aaa contains members to accomodate a fixed number of strings // as well as a pointer to struct bbb struct aaa { char *aaaStr1; char *aaaStr2; char *aaaStr3; char *aaaStr4; char *aaaStr5; struct bbb *pBbb; }; // struct bbb is used to set array order size // (or the number of copies necessary of struct ccc) // it contains the array size (index value) member "numRows" // and a pointer to a struct, which will work like a pointer // to array of struct ccc struct bbb { int numRows; struct ccc *row; }; // struct ccc contains members to accomodate a variable number of // sets of strings, number of sets determined by the array row[] // initialized to array size "numRows" in struct bbb // (see initComplexStructs.c for how this is done) struct ccc { char *cccStr1; char *cccStr2; char *cccStr3; char *cccStr4; char *cccStr5; }; 

InitComplexStructs.c

  /////////////////////////////////////////////////////////// ///// Using nested data structures //////////////////////// /////////////////////////////////////////////////////////// // // client-side gSoap generated code will often use nested // data structures to accomodate complex data types // used in the 4th and 5th arguments of the client // soap_call__ns...() functions. // // This program illustrates how to work with these // structures by a calling application in the // following way : // // - Initialization of structs // - Allocation of structs and members // - Assignment of values to members // - Freeing of allocated memory // /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// #include  #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: The order of array is determined //by the value assigned to "numRows" //Note also: the value for numRows could be passed in by argument //since the calling function has this information. //Just requires prototype mod from void to int argument. p_aaa->pBbb->numRows = 3; p_aaa->pBbb->row = calloc(p_aaa->pBbb->numRows,sizeof(*p_row)); //Allocate the innermost struct ccc accessed through *row for(i=0;ipBbb->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;ipBbb->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;ipBbb->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); } 

¿Sabe que gSOAP asigna memoria para sus estructuras de datos para que no tenga que hacer esto? Solo tiene que asignar memoria para cualquier dato en una estructura de Solicitud, pero nunca una estructura de respuesta.