用于 C++ 的通用 WebService (SOAP) 客户端库

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4285585/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:02:08  来源:igfitidea点击:

Generic WebService (SOAP) client library for C++

c++soapwebservice-client

提问by Patrick

I'm looking for a simple C++ WebService Client Library that can be easily linked into my application.

我正在寻找一个可以轻松链接到我的应用程序的简单 C++ WebService 客户端库。

Preferably this library:

最好是这个库:

  • can be used to access any SOAP WebService (so I can pass the URL, the WebService name, the WebService method and all the arguments as arguments to a function call)
  • can be linked statically in a C++ application (so no DLL's)
  • is freeware or available at a low cost
  • can be used royalty-free in my application
  • can query the Web service for its WSDL and return me the available method names, arguments of the methods and their data types
  • 可用于访问任何 SOAP WebService(因此我可以将 URL、WebService 名称、WebService 方法和所有参数作为参数传递给函数调用)
  • 可以在 C++ 应用程序中静态链接(因此没有 DLL)
  • 是免费软件或以低成本获得
  • 可以在我的应用程序中免版税使用
  • 可以查询 Web 服务的 WSDL 并返回可用的方法名称、方法参数及其数据类型

Before anyone of you answers .NET: been there, tried it. My major objections against .NET are:

在你们中的任何人回答 .NET 之前:去过那里,尝试一下。我对 .NET 的主要反对意见是:

  • you can generate the proxy but it's impossible to change the WebService name in the generated proxy code afterwards, since .NET uses reflection to check the WebService name (see Dynamically call SOAP service from own scripting languagefor my question regarding that problem)
  • generating the proxy class on the fly doesn't always seem to work correctly
  • 您可以生成代理,但之后无法在生成的代理代码中更改 WebService 名称,因为 .NET 使用反射来检查 WebService 名称(有关该问题的问题,请参阅从自己的脚本语言动态调用 SOAP 服务
  • 动态生成代理类似乎并不总是正常工作

I already used Google to look up this information, but I couldn't find one.

我已经使用 Google 查找了此信息,但找不到。

Thanks

谢谢

EDIT:To clarify this further, I really want something where I can write code like this (or something in this style):

编辑:为了进一步澄清这一点,我真的想要一些我可以编写这样的代码(或这种风格的东西)的东西:

SoapClient mySoapClient;
mySoapClient.setURL("http://someserver/somewebservice");
mySoapClient.setMethod("DoSomething");
mySoapClient.setParameter(1,"Hello");
mySoapClient.setParameter(2,12345);
mySoapClient.sendRequest();
string result;
mySoapClient.getResult(result);

No dynamic code generation.

没有动态代码生成。

采纳答案by Patrick

I found a solution using on-the-fly-generated assemblies (which I couldn't get working the previous time). Starting point is http://refact.blogspot.com/2007_05_01_archive.html.

我找到了一个使用即时生成的程序集的解决方案(我以前无法工作)。起点是http://refact.blogspot.com/2007_05_01_archive.html

E.g. This is the code to use the PeriodicTable web service:

例如,这是使用 PeriodicTable 网络服务的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Web;
using System.Web.Services;
using System.Web.Services.Description;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Xml.Serialization;
using System.IO;
using System.Reflection;

namespace GenericSoapClient
{
class Program
    {
    static void method1()
        {
        Uri uri = new Uri("http://www.webservicex.net/periodictable.asmx?WSDL");
        WebRequest webRequest = WebRequest.Create(uri);
        System.IO.Stream requestStream = webRequest.GetResponse().GetResponseStream();

        // Get a WSDL
        ServiceDescription sd = ServiceDescription.Read(requestStream);
        string sdName = sd.Services[0].Name;

        // Initialize a service description servImport
        ServiceDescriptionImporter servImport = new ServiceDescriptionImporter();
        servImport.AddServiceDescription(sd, String.Empty, String.Empty);
        servImport.ProtocolName = "Soap";
        servImport.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties;

        CodeNamespace nameSpace = new CodeNamespace();
        CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
        codeCompileUnit.Namespaces.Add(nameSpace);

        // Set Warnings

        ServiceDescriptionImportWarnings warnings = servImport.Import(nameSpace, codeCompileUnit);

        if (warnings == 0)
            {
            StringWriter stringWriter =
                 new StringWriter(System.Globalization.CultureInfo.CurrentCulture);

            Microsoft.CSharp.CSharpCodeProvider prov =
              new Microsoft.CSharp.CSharpCodeProvider();

            prov.GenerateCodeFromNamespace(nameSpace,
               stringWriter,
               new CodeGeneratorOptions());

            string[] assemblyReferences =
               new string[2] { "System.Web.Services.dll", "System.Xml.dll" };

            CompilerParameters param = new CompilerParameters(assemblyReferences);

            param.GenerateExecutable = false;
            param.GenerateInMemory = true;
            param.TreatWarningsAsErrors = false;

            param.WarningLevel = 4;

            CompilerResults results = new CompilerResults(new TempFileCollection());
            results = prov.CompileAssemblyFromDom(param, codeCompileUnit);
            Assembly assembly = results.CompiledAssembly;
            Type service = assembly.GetType(sdName);

            //MethodInfo[] methodInfo = service.GetMethods();

            List<string> methods = new List<string>();

            // only find methods of this object type (the one we generated)
            // we don't want inherited members (this type inherited from SoapHttpClientProtocol)
            foreach (MethodInfo minfo in service.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
                {
                methods.Add(minfo.Name);
                Console.WriteLine (minfo.Name + " returns " + minfo.ReturnType.ToString());
                ParameterInfo[] parameters = minfo.GetParameters();
                foreach (ParameterInfo pinfo in parameters)
                    {
                        Console.WriteLine("   " + pinfo.Name + " " + pinfo.ParameterType.ToString());
                    }
                }

            // Create instance of created web service client proxy
            object obj = assembly.CreateInstance(sdName);

            Type type = obj.GetType();

            object[] args0 = new object[] { };
            string result0 = (string)type.InvokeMember(methods[0], BindingFlags.InvokeMethod, null, obj, args0);
            Console.WriteLine(result0);

            object[] args1 = new object[] { "Oxygen" };
            string result1 = (string)type.InvokeMember(methods[1], BindingFlags.InvokeMethod, null, obj, args1);
            Console.WriteLine(result1);
            }
        }
    }
}

In this code I explicitly use methods[0]and methods[1]but in reality you would check the method names of course. In this example I get the names of all elements in the periodic table, then get the atomic weight of oxygen.

在这段代码中,我明确使用methods[0]methods[1]但实际上您当然会检查方法名称。在这个例子中,我得到了元素周期表中所有元素的名称,然后得到了氧的原子量。

This example does not yet contain logic to support a proxy. I still need to add this, but for the moment, it solves my biggest problem, namely, having a generic SOAP client.

此示例尚不包含支持代理的逻辑。我仍然需要添加这个,但目前,它解决了我最大的问题,即拥有一个通用的 SOAP 客户端。

EDIT:

编辑:

I know this code is C# and I was originally asking for a C++ solution, but this code proves that it can work in a .NET environment (which I can still use in limited parts of my application), and I will probably rewrite this code into C++/.NET, which solves my problem.

我知道这段代码是 C# 并且我最初是要求一个 C++ 解决方案,但这段代码证明它可以在 .NET 环境中工作(我仍然可以在我的应用程序的有限部分使用),我可能会重写这段代码到 C++/.NET,它解决了我的问题。

回答by Starkey

Have you looked at gSOAP? I think it will be suitable for your needs.

你看过gSOAP吗?我认为它将适合您的需求。

http://gsoap2.sourceforge.net/

http://gsoap2.sourceforge.net/

回答by Ricko M

Axis2C : http://axis.apache.org/axis2/c/core/index.html

Axis2C:http: //axis.apache.org/axis2/c/core/index.html

Axis2C ticks most of the above , please check for static linking. .

Axis2C 勾选了上述大部分内容,请检查静态链接。.

EDIT: As per last few messages on the list, static linking is incomplete. The below still holds:

编辑:根据列表中的最后几条消息,静态链接不完整。以下仍然成立:

Perhaps I do not understand the question correctly. Any web service you call you need to specify the endpoint URL and the operation & parameters.

也许我没有正确理解这个问题。您调用的任何 Web 服务都需要指定端点 URL 以及操作和参数。

Are you referring to dynamically "discovering" the services & presenting the option to call them...? If so I doubt this is possible.

您是指动态“发现”服务并提供调用它们的选项......?如果是这样,我怀疑这是可能的。

If you are referring to generic framework, SOAP messages are client end responsibility any way... You should not have a problem wrapping them under some of the toolkit API's. WSDL code generation is not mandatory. I have written a few services from scratch, i.e. You can set endpoint, service and craft the SOAP message, parameters, headers etc. as you feel.

如果您指的是通用框架,则 SOAP 消息无论如何都是客户端的责任……将它们包装在某些工具包 API 下应该没有问题。WSDL 代码生成不是强制性的。我从头开始编写了一些服务,即您可以根据自己的感觉设置端点、服务和制作 SOAP 消息、参数、标头等。

Cheers!

干杯!