【问题标题】:gSoap - service call returns with SOAP_OK, but return struct uninitializedgSoap - 服务调用返回 SOAP_OK,但返回未初始化的结构
【发布时间】:2011-08-11 02:16:34
【问题描述】:

这是一个空指针解引用问题 - 在 ANSI C 和 gSoap 域中:

我正在使用以下公共WSDL

http://www.mobilefish.com/services/web_service/countries.php?wsdl

并使用soapUI测试了它的行为。
我使用 wsdl2h 和 soapcpp2 实用程序创建了仅客户端的 ANSI C 绑定。

问题:

在以前的 gsoap 项目中,客户端soap_call 函数(第五个参数)中的结果结构不需要初始化,除了以下内容:

struct ns2__countryInfoByIanaResponse out, *pOut
pOut= &out;

在这个项目之前,这一直是足够的。
客户端soap_call 如下所示:

soap_call_ns2__countryInfoByIana(&soap, NULL, NULL, pIn, pOut); /* SOAP 1.2 RPC return element...*/

此项目的pIn 定义为char *,填充有两个字符的IANA 代码,例如“us”或“nz”。此特定调用的返回结构pOut 的形状如下:

struct ns2__countryInfoByIanaResponse
{
    struct ns1__CountryData *countryinfo;
}

ns1__CountryData 的形状是这样的:

struct ns1__CountryData
{
    char *ianacode; /* required element of type xsd:string */
    char *countryname;  /* required element of type xsd:string */
    float latitude; /* required element of type xsd:float */
    float longitude;    /* required element of type xsd:float */
};

因此,我的应用程序对这个函数的调用是这样设置的:

//declare response structure:
struct ns2__countryInfoByIanaResponse o, *pO;

void main(void)
{
   pO = &o;
   if(GetCountryInfo(buf, pO)==0)
   {
      pO->countryinfo->countryname; //Error Occurs Here...
   }                                
}

错误发生在pO->countryinfo 作为空指针的解引用

GetCountryInfo 在这里定义:

int DLL_EXPORT GetCountryInfo(char *pIn, struct ns2__countryInfoByIanaResponse *pOut)
{

    int status = 0;
    size_t len=2048;
    char buf[2048];

    if (soap_call_ns2__countryInfoByIana(&soap, NULL, NULL, pIn, pOut)== SOAP_OK)
    {
        status = 0;
    }
    else
    {
        //soap_print_fault(&soap, stderr);
        soap_sprint_fault(&soap, buf, len);
        MessagePopup("soap error", buf);
        status = 1;
    }
    return status;
}

其他使用类似输出结构形状的gSoap 项目(即包含包含 char * 的结构的结构)在初始化时返回完全填充的结果,除了我上面显示的内容。

有什么想法吗?如果我能提供任何进一步的细节,请告诉我。 谢谢。

【问题讨论】:

    标签: c ansi gsoap


    【解决方案1】:

    在我看来,soap 服务器有一个错误。 countryInfoByIana 函数的示例肥皂响应如下所示:

    <?xml version="1.0" encoding="UTF-8"?>
    <SOAP-ENV:Envelope
            xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
            SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      <SOAP-ENV:Body>
        <SOAP-ENV:countryInfoByIanaResponse>
          <return>
            <ianacode xsi:type="xsd:string">nz</ianacode>
            <countryname xsi:type="xsd:string">New Zealand</countryname>
            <latitude xsi:type="xsd:float">-40.900558</latitude>
            <longitude xsi:type="xsd:float">174.885971</longitude>
          </return>
        </SOAP-ENV:countryInfoByIanaResponse>
      </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    

    &lt;SOAP-ENV:countryInfoByIanaResponse&gt; 应该有不同的命名空间。

    这是 WSDL 的一部分,它包含相同的(无效的)命名空间。

    <operation name="countryInfoByIana">
      <soap:operation soapAction="http://schemas.xmlsoap.org/soap/envelope/#Countries#countryInfoByIana" />
      <input>
        <soap:body use="encoded" namespace="http://schemas.xmlsoap.org/soap/envelope/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
        <soap:body use="encoded" namespace="http://schemas.xmlsoap.org/soap/envelope/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
    </operation>
    

    编辑:

    关于为什么soapUI 工作正常的问题; soapUI 可能不会像 gsoap 那样验证返回值。

    我设法让程序在我的电脑上使用 gsoap 2.7 成功:

    在 soapClient.c 第 56 行,更改此行:

    //soap_get_ns2__countryInfoByIanaResponse(soap, _param_1, "ns2:countryInfoByIanaResponse", "");
    soap_get_ns2__countryInfoByIanaResponse(soap, _param_1, "SOAP-ENV:countryInfoByIanaResponse", "");
    

    在 soapC.c 第 1470 行,更改此行:

    //if (soap_in_PointerTons1__CountryData(soap, "countryinfo", &a->countryinfo, "ns1:CountryData"))
    if (soap_in_PointerTons1__CountryData(soap, "return", &a->countryinfo, "ns1:CountryData"))//return
    

    但我认为你不应该这样解决问题。不仅因为这两个文件都生成了,所以当你再次生成它时你会丢失你的更改。

    【讨论】:

    • 2 个问题:1) 当我在soapUI 中使用这个WSDL 时,它始终返回数据。那么服务器是否对来自soapUI 等实用程序的查询做出不同的响应,而不是gsoap 生成的c 绑定? 2)根据您的经验,在我的 gsoap 生成的代码中是否有一些内容可以编辑以使其查询和响应更类似于使用soapUI 生成的那些?谢谢,瑞克
    • 顺便说一句,你可以用wireshark之​​类的工具来看看gsoap和soapUI发送的数据是不是一样,有什么区别。
    • 感谢您在上面的澄清以及wireshark 提示。我会尝试两者。关于您关于修改生成代码的评论,我同意,但如果我需要将服务与 gSoap 源代码一起使用,则看不到任何解决方法。作为一种解决方法,当我必须进行编辑时,我使用内联 cmets 和更改的文件名来解释更改并保护修改后的文件。再次感谢您的帮助,Ryyker
    猜你喜欢
    • 1970-01-01
    • 2020-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多