【问题标题】:gSoap generated client-side structure initialization and usegSoap生成客户端结构初始化及使用
【发布时间】:2011-08-15 19:37:25
【问题描述】:

gSoap 生成的客户端结构初始化和使用(使用 ANSI C 绑定)

在阅读gSoap 示例和文档后,我无法找到任何直接回答此问题的内容。我已经把它整理出来了。这个帖子/答案对列出了问题和我的解决方案。

问题描述:
我正在使用 gSoap 生成的客户端源代码来构建 ANSI C 绑定以访问 Web 服务。作为应用程序接口(在soapClient.c 中定义)提供的“soap_call__”函数的参数 4 和 5 通常生成为复杂(嵌套)结构。因为struct ns3__send(第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)

soapStub.h 中定义了以下结构定义(仅查看参数 4)

注意:为了简化,我已经缩短了名称并减少了结构的原始内容的成员数量。

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

问题:
这个复杂(嵌套)输入结构中的成员和指针如何正确初始化、分配内存、分配值和释放内存,以便它们在调用应用程序中可用?

【问题讨论】:

    标签: c ansi gsoap


    【解决方案1】:

    注意:这最初发布到由生成的地址结构 gSoap 实用程序,但它一般适用于 任何 嵌套结构 用指针...

    下面描述了一种 ANSI C 方法,用于初始化、分配、分配和释放嵌套结构构造中的成员和指针,其中嵌套部分中的字段数在运行时之前是未知的。

    为了解释需要这种处理的结构的形状,数据模式由 已知header 字段组成,每个字段每行有一个值。最后一个字段(行)用作 headerdata 部分之间的分隔符 ********。数据部分包含 未知 数量的数据记录,但每条记录都包含已知(且恒定)数量的逗号分隔字段:

    示例数据:

    下面显示的两个文件都有完整的注释。他们将一起使用任何 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, 1);
            p_aaa->aaaStr2 = calloc(sizeStr, 1);
            p_aaa->aaaStr3 = calloc(sizeStr, 1);
            p_aaa->aaaStr4 = calloc(sizeStr, 1);
            p_aaa->aaaStr5 = calloc(sizeStr, 1);
            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, 1);
                p_aaa->pBbb->row[i].cccStr2 = calloc(sizeStr, 1);
                p_aaa->pBbb->row[i].cccStr3 = calloc(sizeStr, 1);
                p_aaa->pBbb->row[i].cccStr4 = calloc(sizeStr, 1);
                p_aaa->pBbb->row[i].cccStr5 = calloc(sizeStr, 1);
            }
        }
    
        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);
        }
    

    【讨论】:

    • 嗨。 sizeof(char) 不是按定义等于 1 吗?
    【解决方案2】:

    您是否知道 gSOAP 会为您的数据结构分配内存以便您不必这样做?您只需为请求结构中的任何数据分配内存,而不必为回复结构分配内存。

    【讨论】:

    • 在这个复杂的(嵌套)输入结构中(来自原始帖子中的问题。)
    • 对不起,朋友。没看到那部分。
    • 没关系。当我第一次使用 gSoap 时,我不得不发现分配什么和不分配什么。
    猜你喜欢
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-23
    • 2020-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多