在 C++/CLI 中,如何声明和调用带有“out”参数的函数?

Posted

技术标签:

【中文标题】在 C++/CLI 中,如何声明和调用带有“out”参数的函数?【英文标题】:In C++/CLI, how do I declare and call a function with an 'out' parameter? 【发布时间】:2010-09-16 05:37:21 【问题描述】:

我有一个函数可以将一个字符串解析为两个字符串。在 C# 中,我会这样声明:

void ParseQuery(string toParse, out string search, out string sort)

    ...

我会这样称呼它:

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

当前项目必须在 C++/CLI 中完成。我试过了

using System::Runtime::InteropServices;

...

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

    ...

但如果我这样称呼它:

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

我得到一个编译器错误,如果我这样称呼它:

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

然后我在运行时遇到错误。我应该如何声明和调用我的函数?

【问题讨论】:

我认为应该是using namespace System::Runtime::InteropServices; 而不是using System::Runtime::InteropServices; 【参考方案1】:

不支持。你能得到的最接近的是 ref

当然你可以伪造它,但你会丢失编译时间检查。

【讨论】:

OK...如何在托管 C++ 中声明和调用带有 ref 参数的函数? 不知道为什么这被否决了。实际上它不受支持。当然,您可以伪造它,但是您会丢失编译时检查。这是一个相当大的交易imo C++/CLI 可以调用 C# out 参数,将它们视为 ref 参数。差异似乎只在调用方(C++ 定义与 C# 定义相同,但仍指定 out 并且两者都应限制 C# 调用) 有可能...见上面的答案。你不会再丢失任何东西了,所以你可以删除这篇文章。【参考方案2】:

C++/CLI 本身不支持真正的“输出”参数,但您可以将引用标记为输出参数,以使其他语言将其视为真正的输出参数。

您可以对引用类型执行以下操作:

void ReturnString([Out] String^% value)

   value = "Returned via out parameter";


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

对于值类型为:

void ReturnInt([Out] int% value)

   value = 32;


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

% 使它成为一个 'ref' 参数,OutAttribute 标记它仅用于输出值。

【讨论】:

我认为这与 C# out 修饰符不同。例如,在 C# 中,如果一个参数被标记出来但未分配给它,则会导致编译器错误。你的例子也是这样吗? 这就是 C# 的 out 参数在 IL 级别上的实现方式:只有一个 ref 调用约定,用于 C# 中的 ref 和 out。带有 OutAttribute 的注解使其成为输出参数。 IL 可能相同,但从语言的角度来看,C++ 不支持与 C# out 修饰符相同的东西。同样,它不支持 using() 语句的概念(您使用 try/finally 创建了相同的 IL,但您失去了所有开发优势)。 您可以通过不在变量定义上使用 ^ 轻松重现使用。 MC++ 自动调用 IDisposable。当变量超出范围时释放。 (如果将变量传递给方法,则只需使用 . 而不是 -> 和 %variable) 不要忘记头文件中的using namespace System::Runtime::InteropServices;,否则编译器找不到Out-Attribute。【参考方案3】:

使用 Visual Studio 2008,这有效并解决了我工作中的一个主要问题。谢谢!

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

【讨论】:

以上是关于在 C++/CLI 中,如何声明和调用带有“out”参数的函数?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 C++/CLI 代码调用 C++ 代码?

关于在C语言 声明带有一个变长数组参数的函数

在 C++/CLI 中引用和输出

c语言函数的调用和声明

如何更改aws cli中的默认配置文件变量?

C#怎么调用方法