2008-10-09 7 views
43

Tengo una función que analiza una cadena en dos cadenas. En C# Me gustaría declarar así:En C++/CLI, ¿cómo declaro y llamo a una función con un parámetro 'out'?

void ParseQuery(string toParse, out string search, out string sort) 
{ 
    ... 
} 

y lo llamaría así:

string searchOutput, sortOutput; 
ParseQuery(userInput, out searchOutput, out sortOutput); 

El proyecto actual tiene que ser hecho en C++/CLI. He intentado

using System::Runtime::InteropServices; 

... 

void ParseQuery(String^toParse, [Out] String^ search, [Out] String^ sort) 
{ 
    ... 
} 

pero si yo lo llamo así:

String^searchOutput,^sortOutput; 
ParseQuery(userInput, [Out] searchOutput, [Out] sortOutput); 

me sale un error de compilación, y si lo llamo así:

String^searchOutput,^sortOutput; 
ParseQuery(userInput, searchOutput, sortOutput); 

entonces consigo un error en el tiempo de ejecución. ¿Cómo debo declarar y llamar a mi función?

+0

Creo que debería ser 'using namespace System :: Runtime :: InteropServices;' en lugar de 'using System :: Runtime :: InteropServices;'. – teeks99

Respuesta

67

C++/CLI en sí mismo no es compatible con un argumento de 'salida' real, pero puede marcar una referencia como un argumento de salida para hacer que otros lenguajes lo vean como un argumento de salida real.

Puede hacer esto para los tipos de referencia como:

void ReturnString([Out] String^% value) 
{ 
    value = "Returned via out parameter"; 
} 

// Called as 
String^ result; 
ReturnString(result); 

Y para los tipos de valor como:

void ReturnInt([Out] int% value) 
{ 
    value = 32; 
} 

// Called as 
int result; 
ReturnInt(result); 

El% lo convierte en un parámetro 'ref' y la OutAttribute marca que es sólo utilizado para valores de salida.

+1

No creo que esto sea lo mismo que el modificador C# out. Por ejemplo, en C# si un parámetro marcado y no asignado, resulta en un error de compilación. ¿Es esto lo mismo en tu ejemplo? –

+1

Así es como se implementan los parámetros de C# s en el nivel IL: solo hay una convención de llamada de referencia, que se usa para ref y out en C#. La anotación con un OutAttribute lo convierte en un parámetro de salida. –

+0

Vea también: http://msdn.microsoft.com/en-us/magazine/cc164193.aspx#S2 –

0

No es compatible. Lo más cerca que puede obtener es ref

Concedido, puede falsificarlo, pero pierde una verificación de tiempo de compilación.

+0

OK ... ¿cómo declararía y llamaría a una función con parámetros ref en C++ administrado? – Simon

+1

No estoy seguro de por qué se votó negativamente. Cuando de hecho no es compatible. De acuerdo, puede falsificarlo, pero pierde una verificación de tiempo de compilación. Eso es algo muy importante. Imo –

+0

C++/CLI puede llamar a los parámetros 'out' de C# tratándolos como parámetros 'ref'. La diferencia parece ser solo del lado de la llamada (la definición de C++ es la misma que la definición de C# que todavía especifica 'out' y ambas deberían limitar las llamadas de C#) –

8

Al usar Visual Studio 2008, esto funciona y solucionó un problema importante en mi trabajo. ¡Gracias!

// header 
// Use namespace for Out-attribute. 
using namespace System::Runtime::InteropServices; 
namespace VHT_QMCLInterface { 
    public ref class Client 
    { 
    public: 
     Client(); 
     void ReturnInteger(int a, int b, [Out]int %c); 
     void ReturnString(int a, int b, [Out]String^ %c); 
    } 
} 

// cpp 
namespace VHT_QMCLInterface { 

    Client::Client() 
    { 

    } 

    void Client::ReturnInteger(int a, int b, [Out]int %c) 
    { 
     c = a + b; 
    } 
    void Client::ReturnString(int a, int b, [Out]String^ %c) 
    { 
     c = String::Format("{0}", a + b); 
    } 
} 

// cs 
namespace TestQMCLInterface 
{ 
    class Program 
    { 
     VHT_QMCLInterface.Client m_Client = new VHT_QMCLInterface.Client(); 
     static void Main(string[] args) 
     { 
      Program l_Program = new Program(); 
      l_Program.DoReturnInt(); 
      l_Program.DoReturnString(); 
      Console.ReadKey(); 
     } 

     void DoReturnInt() 
     { 
      int x = 10; 
      int y = 20; 
      int z = 0; 
      m_Client.ReturnInteger(x, y, out z); 
      Console.WriteLine("\nReturnInteger: {0} + {1} = {2}", x, y, z); 
     } 

     void DoReturnString() 
     { 
      int x = 10; 
      int y = 20; 
      String z = "xxxx"; 
      m_Client.ReturnString(x, y, out z); 
      Console.WriteLine("\nReturnString: {0} + {1} = '{2}'", x, y, z); 
     } 
    } 
} 
Cuestiones relacionadas