gSoap生成客户端结构初始化及使用 [英] gSoap generated client-side structure initialization and use

查看:36
本文介绍了gSoap生成客户端结构初始化及使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

gSoap generated client-side structure initialization and use (using ANSI C bindings)

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

After reading through gSoap examples and documentation I was not able to find anything directly answering this issue. I have since sorted it out. This post/answer pair lays out the problem and my solution.

问题描述:
我正在使用 gSoap 生成的客户端源代码来构建 ANSI C 绑定以访问 Web 服务.参数 4 &soap_call__"中的第 5 个作为应用程序接口提供的函数(在 soapClient.c 中定义)通常生成为复杂的(嵌套)结构.因为 struct ns3__send(第 4 个参数)是输入结构,它必须在调用应用程序中声明、初始化、分配和释放.

Problem description:
I am 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 in soapClient.c) are often generated as complex (nested) structures. Because struct ns3__send (4th argument) is the input structure, it must be declared, initialized, allocated and freed within the calling application.

例如,给定以下 gSoap 生成的原型:

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)

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

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

Question:
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?

推荐答案

注意:这最初发布到由生成的地址结构gSoap 专门的实用程序,但它具有通用性适用于任何嵌套结构带指针...

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

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.

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

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:

示例数据:

下面显示的两个文件已完全注释.它们将一起使用任何 ANSI C 编译器进行编译和构建:

The two files shown below are fully commented. Together, they will compile and build with any ANSI C compiler:

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);
    }

这篇关于gSoap生成客户端结构初始化及使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆