我已经广泛搜索了我的问题的答案,并且所有解决方案都是不可接受的,不适用的和/或令人困惑的。
我需要将C++
中实现的函数中的字符串返回给C#
中的调用代码。
返回的字符串需要作为参数而不是返回值返回,因为我需要为某些函数传递/返回多个字符串。字符串的长度各不相同,所以我不能只分配缓冲区等。
任何帮助都将不胜感激。
注意: Justin和/或其他人发布和提及的解决方案不是我的用例的解决方案。正如我在问题中所述,在调用C ++代码之前,我不知道字符串的大小。我无法预先分配StringBuffer并将其传递给C ++代码。
答案 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
和其他类似功能。
另请注意,这会将指针中的数据复制到字符串中。如果你想在适当的位置引用字符串,你必须使用IntPtr
和Marshal
类,或深入研究不安全代码和指针的精彩世界。
答案 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 ++中,您使用SysAllocString
或SysAllocStringLen
。只要你使用正确的签名,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);