我是C ++的新手。我正在使用PINVOKE从C#调用C ++函数,并希望将字符串作为out参数返回。但是我只是得到一个空字符串。 int out参数工作正常。
导入:
[DllImport ( @"UnamanagedAssembly.dll", CharSet = CharSet.Ansi)]
public static extern int Activate(ref int numActivated, StringBuilder eventsActivated);
extern "C" __declspec(dllexport) int Activate(int *p_NumActivated, char *p_EventsActivated) {return Activation::GetInstance()->Activate(p_NumActivated, p_EventsActivated);}
从C#调用我的C ++函数:
int numActivated = 0;
StringBuilder eventsActivated = new StringBuilder();
int status = Activate(ref numActivated, eventsActivated);
C ++函数:
int Activation::Activate(int *p_NumActivated, char *&p_EventsActivated)
{
char *pTemp = "Hello";
p_EventsActivated = pTemp;
*p_NumActivated = 1;
return 0;
}
答案 0 :(得分:3)
StringBuilder eventsActivated = new StringBuilder(5);
而不是
StringBuilder eventsActivated = new StringBuilder();
答案 1 :(得分:2)
[DllImport ( @"UnamanagedAssembly.dll", CharSet = CharSet.Ansi)]
public static extern int Activate(
ref int numActivated,
[MarshalAs(UnmanagedType.LPStr)]StringBuilder eventsActivated);
答案 2 :(得分:1)
P / Invoke仅支持C接口。 YMMV如果你想让它与C ++结构交谈。在这种情况下,您必须具体了解C ++编译器将引用转换为什么,因为C ++编译器可以自由地以任何方式实现它。
如果你想能够进行P / Invoke,但又不想在调用站点使用指针语义,你可以这样做:
int Activation::Activate(int *p_NumActivated, char **p_EventsActivated)
{
return Activate(p_NumActivated, *p_EventsActivated);
}
int Activation::Activate(int *p_NumActivated, char *&p_EventsActivated)
{
char *pTemp = "Hello";
p_EventsActivated = pTemp;
*p_NumActivated = 1;
return 0;
}
它暴露了一个普通的指针,你应该能够更简单地P / Invoke。
但是,请注意,无论您使用哪个字符串,它都可能无法通过相关函数进行修改。这是因为.NET字符串是UTF-16字符串,而C ++函数使用的是ASCII字符串,它们彼此不完全兼容。你可能不得不将.NET字符串转换为ASCII,整理它,整理它,然后重新转换回UTF-16。
哦,最后一件事:如上所述,您需要传递对Activation
对象的引用才能使该函数正常工作。该参数的位置将依赖于C ++编译器。
答案 3 :(得分:0)
请原谅我的答案,如果它是错的,但是:
我不认为StringBuilder与char *&
兼容你是否在使用char **混淆StringBuilder? *您可能希望根据Activate的返回创建一个新字符串或stringbuilder,而不是尝试通过Activate a place来放置数据。 (正如你似乎想做的那样?)
(Activate为“Hello”分配空间,然后将指针返回到其位置)。
通常,在C ++或C对象之间进行编组时,在发送字符串时,最好还发送字符串的长度,以确保在调用者之间传递正确的长度字符串。