2011-04-29 43 views
1

gSOAP的生成的客戶端的結構的初始化和使用(使用ANSI C綁定)gSOAP的生成的客戶端的結構的初始化和使用

首先,我搜索,雖然也有提出了一些結構初始化解決方案,我沒有直接回答這個問題。

而且,這個問題被簡單地張貼到幫助其他人有類似的問題,因爲我已經制定了解決方案,並because of my newbie status會後立即at least 8 hours發佈此之後

不過,我仍然在評論和編輯的解決方案,我會從那些有更好的解決方案,或在gSOAP的更多的經驗提供非常感興趣......

的情景:
我對soap一般都比較陌生,並且一直使用gSoap生成的客戶端源代碼來構建ANSI C綁定來訪問Web服務。作爲應用程序接口(在soapClient.c中定義)提供的「soap_call__」函數的5個參數多次是複雜的(嵌套的)結構。參數4特別是因爲它是輸入結構,必須在調用應用程序中聲明,初始化,分配和釋放。

例如,給定以下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) 

具有以下結構定義(僅在參數4看)在soapStub.h定義

(注:我已縮短爲了說明的目的,從結構的原始內容中刪除名稱並減少了成員的數量)

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

的問題是:

如何此複合物(嵌套的)輸入結構內的構件和指針正確初始化,存儲器分配,分配的值和存儲器釋放,使得它們調用應用內可用?

回答

3

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

地址嵌套結構內初始化,分配,分配和釋放構件和指針的問題構建ANSI C.

爲了解釋需要這種治療的結構的形狀,該數據模式是由一個已知號的報頭字段,每行各自具有一個值,隨後由分隔符********的,隨後由未知數量的數據字段,每個具有一個已知的(和常數)數以逗號分隔的字段:

實施例的數據:
enter image description here

下面顯示的兩個文件已完整註釋。他們將一起編譯和任何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 <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: 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;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); 
    } 
0

你意識到了嗎gSOAP爲你的數據結構分配內存,這樣你就沒有t了o這樣做?您只需爲請求結構中的任何數據分配內存,但永遠不會有回覆結構。

+0

_within此複雜(嵌套)輸入結構_(來自原始帖子中的問題) – ryyker 2014-06-11 21:28:25

+0

對不起,朋友。沒有看到那部分。 – Vistian 2014-10-19 20:50:51

+0

沒關係。我第一次使用gSoap時,我必須發現要分配什麼以及哪些不能很難分配。 – ryyker 2014-10-19 21:51:35