如何将 C++/CLI 字符串转换为常量字符*

How to convert C++/CLI string to const char*

本文关键字:转换 常量 字符 字符串 CLI C++      更新时间:2023-10-16

我有一个C++/CLI DLL,我计划将其用作C# DLL和本机C++客户端之间的适配器。我需要在两个方向上传递字符串。适配器是使用 VS2013 编译的,但需要支持使用 VS2008 构建的客户端,所以我在 API 中使用了 const char*。但是即使两者都是VS2013构建的,我所拥有的也无法正常工作。

在其他地方,我找到了使用 msclr\marshal.h 的建议,所以我创建了:

using namespace msclr::interop;
System::String^ ToCliString(const char* s)
{
    System::String ^result = marshal_as<System::String^>(s);
    return result;
}    
const char* ToCppString(System::String^ s)
{
    msclr::interop::marshal_context context;
    const char* result = context.marshal_as<const char*>(s);
    return result;
}

为了测试这些,我在 C++/CLI DLL 中创建了一个往返转换方法:

const char* Foo(const char *cstar)
{
    System::String^ cli = ::ToCliString(cstar);
    if (cli == "abc")
    {
        MessageBox::Show("const char* -> CLI: OK");
    }
    const char* cstar2 = ::ToCppString(cli);
    if (std::strcmp(cstar2, "abc") == 0)
    {
        MessageBox::Show("CLI -> const char*: OK");
    }
    else if (std::strcmp(cstar2, "") == 0)
    {
        MessageBox::Show("ToCppString returned empty string");
    }
    else
    {
        MessageBox::Show("ToCppString returned something else");
    }
    return cstar2;
}

当本机C++客户端调用 Foo("abc") 时,将显示第一条消息,显示"返回其他内容"消息,并且客户端收到垃圾 (îþîþîþþϾ›vÚ§)。所以看起来我的第二次转换不起作用。

更新

这是我使用的最终解决方案。

我使用了 zneaks 对 std::string 的元帅建议和 PaulMcKenzie 的建议来传递调用者分配的 char* 而不是返回 const char*。谢谢你们。

void ToCppString(System::String^ input, char* output)
{
    std::string temp= marshal_as<std::string>(input);
    strcpy(output, temp.c_str());
}
void Foo(const char* input, char* output)
{
    System::String^ cli = ::ToCliString(input);
    ::ToCppString(cli, output);
}

问题是marshal_context拥有你得到的 char 指针,所以当你的函数返回时,它被释放:

此示例创建一个上下文,用于将 System::String 封送到 const char * 变量类型。转换后的数据在删除上下文的行之后将无效。

请考虑改用marshal_as<std::string>,因为允许字符串的寿命超过marshal_context

此外,请注意,VC++ 2008 Express 不包含封送头文件(marshal.h 等),因此您必须使用 VC++ 2008 专业版或更高版本。看起来这些头文件自VS2010以来包含在速成版中。