0

我已经广泛搜索了我的问题的答案,所有的解决方案都是不可接受的、不适用的和/或令人困惑的。

我需要将一个字符串从实现的函数C++返回到调用代码中C#

返回的字符串需要作为参数而不是返回值返回,因为我需要为某些函数传递/返回多个字符串。字符串的长度各不相同,所以我不能只分配一个缓冲区等。

任何帮助,将不胜感激。

注意:贾斯汀和/或其他人发布和提到的解决方案不是我用例的解决方案。正如我在问题中所述,在调用 C++ 代码之前我不知道字符串的大小。我无法预先分配 StringBuffer 并将其传递给 C++ 代码。

4

3 回答 3

2

一种方法是将参数声明为ref IntPtr. 所以:

static extern void DoSomething(ref IntPtr returnedString);

所以你调用它并得到一个字符串:

IntPtr pstr;
DoSomething(ref pstr);
string theString = Marshal.PtrToStringAnsi(pstr);

但是,重要的是要记住返回的指针是由您的 C++ 代码分配的。如果你希望它被释放,你需要调用 C++ 代码来完成它。

您可能还想查看Marshal.PtrToStringAuto, 和其他类似的功能。

另请注意,这会将数据从指针复制到字符串。如果您想在适当的位置引用字符串,您将不得不使用IntPtrMarshal,或者深入研究不安全代码和指针的奇妙世界。

于 2013-08-19T14:00:58.573 回答
0

添加到吉姆米歇尔的答案,我会创建一个辅助函数,比如

String FromCppString(IntPtr a_Pointer)
{
    String result = Marshal.PtrToStringAnsi(a_Pointer);
    FreeCppString(a_Pointer);
    return result;
}

FreeCppString从 C++ 导出的另一个函数在哪里,可以正确释放字符串。原始的 c++ 函数将根据需要分配尽可能多的字符串并将它们放入参数中。C# 函数将使用 FromCppString() 来提取它们。

于 2013-08-19T14:10:33.987 回答
0

使用平台提供的可移植(多编译器多语言)字符串,用于在以不同语言实现的组件之间传递字符串的明确目的—— BSTR.

在 C++ 中,您使用SysAllocStringor SysAllocStringLenSysFreeString只要您使用正确的签名,P/invoke 已经知道如何处理这些(转换为 .NET 字符串并调用)。

extern static void DoSomething([MarshalAs(UnmanagedType.BStr)] out String returnedString);

然后简单地调用它:

string theString;
DoSomething(out theString);

就是这样,不需要特殊的转换或清理,因为 p/invoke 已经处理好了。

有关更多信息,请阅读有关 p/invoke 中字符串处理的 MSDN 页面

注意:我猜链接中的所有示例都不这种情况,所以这里是 C++ 原型

void DoSomething(__out BSTR *s);
于 2013-08-19T14:27:32.743 回答