如何使用P / INVOKE将c ++ char *编组为C#字符串

时间:2010-07-19 03:36:05

标签: c# c++ pinvoke marshalling unmanaged

我是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;
}

4 个答案:

答案 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对象之间进行编组时,在发送字符串时,最好还发送字符串的长度,以确保在调用者之间传递正确的长度字符串。