Failed to compile gsoap-generated server code with C++ Builder

800 Views Asked by At

I am trying to build a server application using gsoap 2.8.17. I've created a header file with service function prototype and a result record definition

testserver.h:

#ifndef TESTSERVER_H
#define TESTSERVER_H

#include <string>

//gsoap ns service name: TestServer
//gsoap ns service namespace: http://mycomp:8080/TestServer.wsdl
//gsoap ns service location: http://mycomp:8080/TestServer.cgi
//gsoap ns schema namespace: urn:TestServer

class Record
{
public:
    int id;
    std::string name;
    std::string address;
    double param1;
};

int ns__GetRecord(int id, Record* result);

#endif 

Then I've invoked the gSOAP RPC compiler:

soapcpp2.exe testserver.h

The compiler produced the following files:

soapC.cpp
soapClient.cpp
soapClientLib.cpp
soapServer.cpp
soapServerLib.cpp
soapH.h
soapStub.h
TestServer.h
TestServer.nsmap
TestServer.wsdl
TestServer.GetRecord.req.xml
TestServer.GetRecord.res.xml
ns.xsd

TestServer.wsdl

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="TestServer"
 targetNamespace="http://mycomp:8080/TestServer.wsdl"
 xmlns:tns="http://mycomp:8080/TestServer.wsdl"
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:ns="urn:TestServer"
 xmlns:SOAP="http://schemas.xmlsoap.org/wsdl/soap/"
 xmlns:HTTP="http://schemas.xmlsoap.org/wsdl/http/"
 xmlns:MIME="http://schemas.xmlsoap.org/wsdl/mime/"
 xmlns:DIME="http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/"
 xmlns:WSDL="http://schemas.xmlsoap.org/wsdl/"
 xmlns="http://schemas.xmlsoap.org/wsdl/">

<types>

 <schema targetNamespace="urn:TestServer"
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:ns="urn:TestServer"
  xmlns="http://www.w3.org/2001/XMLSchema"
  elementFormDefault="unqualified"
  attributeFormDefault="unqualified">
  <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
  <complexType name="Record"><!-- Record -->

   <sequence>
     <element name="id" type="xsd:int" minOccurs="1" maxOccurs="1"/><!-- Record::id -->
     <element name="name" type="xsd:string" minOccurs="1" maxOccurs="1"/><!-- Record::name -->
     <element name="address" type="xsd:string" minOccurs="1" maxOccurs="1"/><!-- Record::address -->
     <element name="param1" type="xsd:double" minOccurs="1" maxOccurs="1"/><!-- Record::param1 -->
   </sequence>
  </complexType>
  <!-- operation request element -->
  <element name="GetRecord">
   <complexType>
    <sequence>
     <element name="id" type="xsd:int" minOccurs="1" maxOccurs="1"/><!-- ns__GetRecord::id -->
    </sequence>
   </complexType>
  </element>
  <!-- operation response element -->
  <element name="GetRecordResponse">
   <complexType>
    <sequence>
     <element name="result" type="ns:Record" minOccurs="0" maxOccurs="1" nillable="true"/><!-- ns__GetRecord::result -->
    </sequence>
   </complexType>
  </element>
 </schema>

</types>

<message name="GetRecordRequest">
 <part name="Body" element="ns:GetRecord"/><!-- ns__GetRecord::ns__GetRecord -->
</message>

<message name="GetRecordResponse">
 <part name="Body" element="ns:GetRecordResponse"/>
</message>

<portType name="TestServerPortType">
 <operation name="GetRecord">
  <documentation>Service definition of function ns__GetRecord</documentation>
  <input message="tns:GetRecordRequest"/>
  <output message="tns:GetRecordResponse"/>
 </operation>
</portType>

<binding name="TestServer" type="tns:TestServerPortType">
 <SOAP:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
 <operation name="GetRecord">
  <SOAP:operation soapAction=""/>
  <input>
     <SOAP:body parts="Body" use="literal"/>
  </input>
  <output>
     <SOAP:body parts="Body" use="literal"/>
  </output>
 </operation>
</binding>

<service name="TestServer">
 <documentation>gSOAP 2.8.17 generated service definition</documentation>
 <port name="TestServer" binding="tns:TestServer">
  <SOAP:address location="http://mycomp:8080/TestServer.cgi"/>
 </port>
</service>

</definitions>

As documentation recommends I added soapServerLib.cpp to my project, but the C++ Builder 2010 compiler produces errors:

[BCC32 Error] soapC.cpp(1611): E2238 Multiple declaration for 'ns__GetRecord(soap *,int,Record *)'
[BCC32 Error] soapStub.h(224): E2344 Earlier declaration of 'ns__GetRecord(soap *,int,Record *)'
[BCC32 Error] soapC.cpp(1611): E2303 Type name expected
[BCC32 Error] soapC.cpp(1611): E2379 Statement missing ;
[BCC32 Error] soapC.cpp(1717): E2379 Statement missing ;

soapStub.h(224):

SOAP_FMAC5 int SOAP_FMAC6 ns__GetRecord(struct soap*, int id, Record *result);

soapC.cpp(1598-1619):

SOAP_FMAC1 struct ns__GetRecord * SOAP_FMAC2 soap_instantiate_ns__GetRecord(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size)
{
    (void)type; (void)arrayType; /* appease -Wall -Werror */
    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_ns__GetRecord(%d, %s, %s)\n", n, type?type:"", arrayType?arrayType:""));
    struct soap_clist *cp = soap_link(soap, NULL, SOAP_TYPE_ns__GetRecord, n, soap_fdelete);
    if (!cp)
        return NULL;
    if (n < 0)
    {   cp->ptr = (void*)SOAP_NEW(struct ns__GetRecord);
        if (size)
            *size = sizeof(struct ns__GetRecord);
    }
    else
    {   cp->ptr = (void*)SOAP_NEW_ARRAY(struct ns__GetRecord, n); // <<<-- error here
        if (size)
            *size = n * sizeof(struct ns__GetRecord);
    }
    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated location=%p\n", cp->ptr));
    if (!cp->ptr)
        soap->error = SOAP_EOM;
    return (struct ns__GetRecord*)cp->ptr;
}

Why is ns__GetRecord interpreted as a structure while it's a function name? What should I fix in my TestServer.h to make soapcpp2.exe produce a compilable code ?

1

There are 1 best solutions below

0
On

The only solution I found is to remove the soap_instantiate_ns__GetRecord function body.

SOAP_FMAC1 struct ns__GetRecord * SOAP_FMAC2 soap_instantiate_ns__GetRecord(struct 
    soap *soap, int n, const char *type, const char *arrayType, size_t *size)
{
    return NULL;
}

Then the server code compiles and works fine.