2010-11-26 33 views
12

Busco un simple biblioteca de clientes de C++ servicio Web que puede ser fácilmente vinculado en mi aplicación.biblioteca de servicio Web (SOAP) cliente genérico para C++

Preferiblemente esta biblioteca:

  • puede ser utilizado para acceder a cualquier WebService de SOAP (por lo que puede pasar el URL, el nombre WebService, el método WebService y todos los argumentos como argumentos de una llamada de función)
  • pueden vincularse estáticamente en una aplicación de C++ (por lo que no DLL)
  • es freeware o disponibles a un bajo costo
  • se puede utilizar sin derechos de autor en mi solicitud
  • puede consultar la web servic e para su WSDL y devolverme los nombres de métodos disponibles, los argumentos de los métodos y sus tipos de datos

Antes de que cualquiera de ustedes responda .NET: estado allí, lo intenté. Mis principales objeciones contra .NET son:

  • puede generar el proxy pero es imposible cambiar el nombre de servicio Web en el código proxy generado después, desde .NET utiliza la reflexión para comprobar el nombre del servicio Web (ver Dynamically call SOAP service from own scripting language a mi pregunta con respecto a ese problema)
  • generar la clase de proxy sobre la marcha no siempre parece funcionar correctamente

ya he usado Google para buscar esta información, pero no pude encontrar uno.

Gracias

EDIT: Para aclarar esto más, lo que realmente quiero algo donde puedo escribir código como este (o algo en este estilo):

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

Ninguna generación dinámica de código.

Respuesta

4

Encontré una solución usando ensamblajes generados sobre la marcha (que no pude obtener trabajando la vez anterior). El punto de inicio es http://refact.blogspot.com/2007_05_01_archive.html.

E.g. Este es el código para utilizar el servicio web 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); 
      } 
     } 
    } 
} 

En este código que utilizo de manera explícita methods[0] y methods[1] pero en realidad se comprobaría los nombres de los métodos de golf. En este ejemplo, obtengo los nombres de todos los elementos en la tabla periódica y luego obtengo el peso atómico del oxígeno.

Este ejemplo aún no contiene lógica para admitir un proxy. Todavía necesito agregar esto, pero por el momento, resuelve mi mayor problema, es decir, tener un cliente SOAP genérico.

EDIT:

Sé que este código es C# y yo estaba originalmente pidiendo un C++ solución, pero este código demuestra que puede funcionar en un entorno .NET (que todavía puedo usar en partes limitadas de mi aplicación), y probablemente reescribo este código en C++/.NET, que resuelve mi problema.

+0

¡Es un buen punto! ¿Crees que se puede portar al entorno de C++ Builder? ¿O depende de .NET y Reflection? – bluish

+0

@bluish, esto es realmente dependiente de .Net. El código usa .Net para generar la clase de cliente, y luego usa el compilador .Net C# para compilarlo, y usa la reflexión .Net para llamar a la clase. – Patrick

+3

Aunque estoy contento de que el problema del OP esté resuelto, creo que esta respuesta simplemente no puede ser la respuesta aceptada de esta pregunta, ya que está en C# mientras la pregunta es específicamente sobre C++ ... – zgyarmati

5

¿Has mirado en gSOAP? Creo que será adecuado para sus necesidades.

http://gsoap2.sourceforge.net/

+1

Parece que gSOAP genera código CPP. Esto todavía requiere que genere código CPP específico del cliente. Lo que quiero es una clase simple de C++ (o un conjunto de clases), donde simplemente puedo especificar la URL, el nombre del servicio web, el método del servicio web y los argumentos. – Patrick

+0

Investigué mucho sobre las interfaces SOAP de C++ y SOGS es el mejor que existe. * suspiro * ¡Buena suerte! – Starkey

+1

Probablemente GSOAP es el mejor si conoce el WSDL de antemano. Pero, ¿qué ocurre si el nombre, los métodos y los argumentos del servicio web pueden diferir en cada cliente, y quiero leer esta información de un archivo de configuración y realizar las llamadas en función del contenido del archivo de configuración? – Patrick

0

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

Axis2C garrapatas más de los anteriores, por favor, compruebe si la vinculación estática. .

EDIT: Según últimos mensajes de la lista, la vinculación estática es incompleta. El siguiente todavía se tiene:

Tal vez no entiendo la pregunta correctamente. Cualquier servicio web al que llame debe especificar el punto final URL y los parámetros de operación &.

¿Se refiere a la dinámica "descubrir" los servicios & que presentan la opción de llamar a ellos ...? Si es así, dudo que esto sea posible.

Si se refiere a marco genérico, los mensajes SOAP son responsabilidad del cliente final de cualquier manera ...No debería tener problemas para incluirlos en algunas de las API de Toolkit. La generación de código WSDL no es obligatoria. He escrito algunos servicios desde cero, es decir, puede establecer el punto final, el servicio y crear el mensaje SOAP, los parámetros, los encabezados, etc., como lo considere.

¡Salud!

+1

¿Podría publicar algún ejemplo (o enlaces)? – bluish

Cuestiones relacionadas