创建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 <?xml version="1.0" encoding="UTF-8"?> <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
前缀对应的URI :http://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">
<soapenv:Header/>
<soapenv:Body>
<ns:add>
<a>10.5</a>
<b>2.3</b>
</ns:add>
</soapenv:Body>
</soapenv:Envelope>'

===============================
您观察到的现象是正确的,这是因为您使用了 -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
。 -
两种风格功能等效,选择取决于项目需求。