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

发布于 2024-10-04 04:31:22 字数 1059 浏览 0 评论 0原文

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

最好是这个库:

  • 可用于访问任何 SOAP WebService(因此我可以将 URL、WebService 名称、WebService 方法和所有参数作为参数传递给函数调用)
  • 可在 C++ 应用程序中静态链接(因此无需 DLL )
  • 是免费软件或以低成本提供
  • 可以在我的应用程序中免版税使用
  • 可以查询 Web 服务的 WSDL 并向我返回可用的方法名称、方法的参数及其数据类型

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

  • 您可以生成代理,但之后无法在生成的代理代码中更改 WebService 名称,因为 .NET 使用反射来检查 WebService 名称(请参阅 从自己的脚本语言动态调用 SOAP 服务以解决我关于该问题的问题)
  • 动态生成代理类似乎并不总是能正常工作

我已经使用谷歌来查找这些信息,但我找不到。

谢谢

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

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);

没有动态代码生成。

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

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

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

  • 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 language for my question regarding that problem)
  • generating the proxy class on the fly doesn't always seem to work correctly

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陌伤ぢ 2024-10-11 04:31:22

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

http://gsoap2.sourceforge.net/

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

http://gsoap2.sourceforge.net/

入怼 2024-10-11 04:31:22

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

例如,这是使用 periodictable web 服务的代码:

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);
            }
        }
    }
}

在此代码中,我明确使用 methods[0]methods[1] 但实际上您将检查方法名称当然。在此示例中,我获取元素周期表中所有元素的名称,然后获取氧的原子量。

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

编辑:

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

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.

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

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.

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.

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.

胡渣熟男 2024-10-11 04:31:22

<罢工>
Axis2C:http://axis.apache.org/axis2/c/core/index .html

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

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

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

您是指动态“发现”服务和服务吗?提供给他们打电话的选项...?如果是这样,我怀疑这是可能的。

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

干杯!


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

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

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.

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.

Cheers!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文