如何马歇尔c++;使用P/INVOKE将char*转换为C#字符串 我是C++新手。我用pjik调用C++中的C++函数,并希望把字符串作为OUT参数返回。然而,我只是得到一个空字符串回来。int out参数工作正常

如何马歇尔c++;使用P/INVOKE将char*转换为C#字符串 我是C++新手。我用pjik调用C++中的C++函数,并希望把字符串作为OUT参数返回。然而,我只是得到一个空字符串回来。int out参数工作正常,c#,c++,pinvoke,marshalling,unmanaged,C#,C++,Pinvoke,Marshalling,Unmanaged,进口: [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

进口:

[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++函数:< /P>

C++函数:

int Activation::Activate(int *p_NumActivated, char *&p_EventsActivated)
{
    char *pTemp = "Hello";
    p_EventsActivated = pTemp;

    *p_NumActivated = 1;

    return 0;
}

请原谅我的回答有误,但是:

我认为StringBuilder与char不兼容*&

您是否将StringBuilder与char**混淆了? *您可能希望根据Activate的返回创建一个新字符串或stringbuilder,而不是尝试传递Activate位置来放置数据。(就像你想做的那样?)

(Activate为“Hello”分配空间,然后将指针返回到其位置)


一般来说,在C++或C对象之间进行编组时,在发送字符串时,最好也发送字符串的长度,以确保调用方之间传递适当长度的字符串。YMMV,如果你想让它与C++构造对话。在这种情况下,你必须特别地找出C++编译器把引用翻译成什么,因为C++编译器可以随意地实现它。

[DllImport ( @"UnamanagedAssembly.dll", CharSet = CharSet.Ansi)]
public static extern int Activate(
    ref int numActivated, 
    [MarshalAs(UnmanagedType.LPStr)]StringBuilder eventsActivated);
如果您希望能够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

哦,最后一件事:如前所述,您需要传递对
激活
对象的引用,以便该函数工作。这个论点的位置将是C++编译器依赖的。
StringBuilder eventsActivated = new StringBuilder(5);
而不是

StringBuilder eventsActivated = new StringBuilder();

我试着加上,但还是有问题。干杯!它是指向字符指针的引用,而不是指向字符的简单指针。您所发布的内容以10种不同的方式显示了未定义的行为。在仔细检查时,我不确定在C++函数签名中,<代码> char *和pyEvests激活的意味着什么。您是否打算阅读激活的char*p_事件?编辑:啊,我明白了-引用指针。这不是我用过的结构,所以完全不要理我。干杯。我要试一试。什么是最简单的方法来传递一个字符串的任意长度(或在一些大的最大长度无论如何)从C++到C ^。听起来好像我做的事情不像我想象的那么容易:“Trayyb:它可以很简单——但是如果C++代码也使用UTF 16,那就是更容易了,也就是说,<代码> W查尔特特< /Cord>和朋友而不是<代码> char < /代码>。C#是一个unicode环境。如果你不这样做,C++是不存在的。注意,W查尔夫和朋友不会自动暗示Unicode。它可能在使用UCS2。@Arafangion:对于99%的情况,没有区别。BMP涵盖了现代使用的所有语言。但是我想如果你想学究气的话……除非你想和亚洲语言的翻译人员一起工作,他们仍然可以使用BMP,但是他们不会有他们想要使用的全部字符。你不需要在字符串的方法定义中添加ref或out关键字吗?
StringBuilder eventsActivated = new StringBuilder();