> 技术文档 > Ubuntu22 上,用C++ gSoap 创建一个简单的webservice

Ubuntu22 上,用C++ gSoap 创建一个简单的webservice

创建calc.h

// calc.h
// gSOAP 服务定义
int ns__add(double a, double b, double &result);
int ns__subtract(double a, double b, double &result);

==========================

创建my_server.cpp

#include \"soapService.h\"
#include \"ns.nsmap\" 

class MyService : public Service {
public:
    int add(double a, double b, double &result) override {
        result = a + b;
        return SOAP_OK;
    }
    int subtract(double a, double b, double &result) override {
        result = a + b;
        return SOAP_OK;
    }
};

int main() {
    MyService service;
    service.run(8080); // 启动服务
    return 0;
}

========================

在soapService.cpp

增加两个函数

int Service::add(double a, double b, double &result) {
    result = a + b;
    return SOAP_OK;
}

int Service::subtract(double a, double b, double &result) {
    result = a - b;
    return SOAP_OK;
}

==============================

用C++风格,编译生成server

g++ -std=c++11 my_server.cpp soapC.cpp soapService.cpp -o server -lgsoap++

运行

./server

===============================

查看namespace

root@102:/usr/local/src/testCode# cat ns.wsdl <definitions name=\"Service\" targetNamespace=\"http://tempuri.org/ns.xsd/Service.wsdl\" xmlns:tns=\"http://tempuri.org/ns.xsd/Service.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=\"http://tempuri.org/ns.xsd\"

------------------

ns 前缀对应的URIhttp://tempuri.org/ns.xsd,后面的curl测试会用的namespace -----H \'SOAPAction: \"http://tempuri.org/ns.xsd#add\"\' \\

------------------------

用curl 测试

curl -X POST http://localhost:8080 \\
-H \"Content-Type: text/xml\" \\
-H \'SOAPAction: \"http://tempuri.org/ns.xsd#add\"\' \\
-d \'<soapenv:Envelope 
      xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"
      xmlns:ns=\"http://tempuri.org/ns.xsd\">
   
   
       
            10.5
            2.3
       
   
\'

===============================

您观察到的现象是正确的,这是因为您使用了 -S 选项(生成纯 C 代码风格的服务端),而之前的示例是基于 C++ 风格的代码生成(使用 -j 选项)。以下是详细解释和解决方案:


1. 关键区别:-S 和 -j 选项

选项 生成文件命名 代码风格 适用场景 -S soapService.cpp C 风格(函数式) 纯 C 项目 -j soap**calc**Service.cpp C++ 风格(面向对象) C++ 项目

您的命令 soapcpp2 -j -S -x calc.h 中:

  • -j 和 -S 同时存在时,-S 优先级更高,因此生成的是 C 风格文件 soapService.cpp

  • 如果去掉 -S,会生成 C++ 风格的 soapcalcService.cpp


2. 生成的文件说明(您的实际输出)

文件名 用途 soapService.cpp C 风格的服务端框架(等效于 soapcalcService.cpp 的 C 版本) soapService.h 服务端头文件 soapC.cpp 公共序列化代码 ns.wsdl WSDL 服务描述文件 ns.nsmap 命名空间映射表

3. 如何生成 C++ 风格代码?

移除 -S 选项,仅保留 -j

bash

soapcpp2 -j -x calc.h

此时会生成:

  • soapcalcService.cpp(C++ 服务端框架)

  • calcService.h(C++ 服务类头文件)


4. 您的下一步选择

选项 1:继续使用 C 风格(当前生成的文件)
  • 服务端实现示例(直接修改 soapService.cpp):

    c

    #include \"soapH.h\"int ns__add(struct soap *soap, double a, double b, double *result) { *result = a + b; return SOAP_OK;}int main() { struct soap soap; soap_init(&soap); soap_serve(&soap); // 启动服务(默认端口8080) return 0;}
  • 编译命令

    bash

    gcc soapService.cpp soapC.cpp -o server -lgsoap
选项 2:改用 C++ 风格(推荐)

重新生成代码:

bash

soapcpp2 -j -x calc.h
  • 服务端实现示例(继承 calcService 类):

    cpp

    #include \"calcService.h\"class MyService : public calcService {public: int add(double a, double b, double &result) override { result = a + b; return SOAP_OK; }};int main() { MyService service; service.run(8080); // 启动服务 return 0;}
  • 编译命令

    bash

    g++ -std=c++11 my_server.cpp soapC.cpp soapcalcService.cpp -o server -lgsoap++

5. 为什么文件名不同?

  • C 风格:统一命名为 soapService.cpp

  • C++ 风格:文件名包含接口前缀(如 soap**calc**Service.cpp),便于多接口区分。


总结

  • 您当前生成的是 C 风格 代码(因 -S 选项)。

  • 如需 C++ 风格,移除 -S 并保留 -j

  • 两种风格功能等效,选择取决于项目需求。