从C#调用C ++返回长度未知的字符串

时间:2013-08-19 13:50:50

标签: c# c++ .net string parameter-passing

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

我需要将C++中实现的函数中的字符串返回给C#中的调用代码。

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

任何帮助都将不胜感激。

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

3 个答案:

答案 0 :(得分: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类,或深入研究不安全代码和指针的精彩世界。

答案 1 :(得分:0)

根据Jim Michel的回答,我会创建一个辅助函数,比如

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

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

答案 2 :(得分:0)

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

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

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

然后简单地称之为:

string theString;
DoSomething(out theString);

就是这样,不需要特殊的转换或清理,因为p / invoke会处理它。

有关详情,请参阅this MSDN page on string handling in p/invoke

注意:我猜这个链接中没有一个例子完全这种情况,所以这里是C ++原型

void DoSomething(__out BSTR *s);