【问题标题】:What is the best way to convert between char* and System::String in C++/CLI在 C++/CLI 中转换 char* 和 System::String 的最佳方法是什么
【发布时间】:2010-09-08 13:34:29
【问题描述】:

在 C++/CLI 中从 char* 转换为 System::string 并返回的批准方法是什么?我在 Google 上找到了一些对 marshal_to 模板化函数的引用,但似乎此功能从未适用于 Visual Studio 2005(并且在 Visual Studio 2008 中也不适用,AFAIK)。我还在Stan Lippman's blog 上看到了一些代码,但它是从 2004 年开始的。我还看到了 Marshal::StringToHGlobalAnsi()。有没有一种被认为是“最佳实践”的方法?

【问题讨论】:

    标签: .net string c++-cli


    【解决方案1】:

    System::String 有一个构造函数,它接受一个 char*:

     using namespace system;
     const char* charstr = "Hello, world!";
     String^ clistr = gcnew String(charstr);
     Console::WriteLine(clistr);
    

    找回一个 char* 有点困难,但还不错:

     IntPtr p = Marshal::StringToHGlobalAnsi(clistr);
     char *pNewCharStr = static_cast<char*>(p.ToPointer());
     cout << pNewCharStr << endl;
     Marshal::FreeHGlobal(p);
    

    【讨论】:

    • +1,System::String 构造函数也需要长度和编码!
    • Marshal::StringToHGlobalAnsi 与使用 RAII 自动释放缓冲区的 marshal_context(如 Matthew 所述)相比是一个糟糕的选择。更不用说名称完全错误,它根本不返回HGLOBAL
    • 您的示例在使用 .NET 4.6.1 的 C++/CLI 中对我不起作用。没有接受 char* 的 System::String 构造函数...只有带符号的 char* 或 wchar_t*
    • 我已经有一段时间没有来到这个世界了,但我相信这应该仍然有效。根据docs.microsoft.com/en-us/cpp/windows/… 的文档,您仍然应该能够以char * 字符串作为参数的gcnew 字符串。也许你可以投到signed char *
    • 根据我的经验,指针也没有 nul 终止符。您需要使用 clistr.Length 才能知道它有多长。
    【解决方案2】:

    这里有一个很好的概述(为 VS2008 添加了这种编组支持): http://www.codeproject.com/KB/mcpp/OrcasMarshalAs.aspx

    【讨论】:

    • 谢谢,但这是一个冗长的解释。这更重要:#include &lt;msclr\marshal.h&gt; // marshal_context context; // my_c_string = context.marshal_as&lt;const char*&gt;(my_csharp_string);
    • 对于那些想知道的人,上下文的完整命名空间是msclr::interop::marshal_context
    【解决方案3】:

    我们所做的是创建一个 C++\CLI 对象,该对象将字符串保存在未修改的代码中,并会给出项目的管理副本。转换代码看起来很像 Stan 在他的博客上的代码(我记不清了)(如果你使用他的代码,请确保更新它以使用 delete[])但我们确保析构函数会处理释放所有对象的未管理元素。这有点夸大其词,但是当我们绑定到遗留 C++ 代码模块时,我们没有泄漏。

    【讨论】:

      【解决方案4】:

      我创建了一些辅助方法。我需要这样做才能从旧的 Qt 库迁移到 CLI String。如果有人可以补充这一点并告诉我我是否有内存泄漏以及我可以做些什么来解决它,我将不胜感激。

      void MarshalString (  String ^ s, wstring& os ) {
          using namespace Runtime::InteropServices;
          const wchar_t* char = (const wchar_t*)(Marshal::StringToHGlobalUni(s)).ToPointer();
          os = char;
      }
      QString SystemStringToQt( System::String^ str)
      {
          wstring t;
          MarshalString(str, t);
          QString r = QString::fromUcs2((const ushort*)t.c_str());
          return r;
      }
      

      【讨论】:

      • 可能必须 Marshal::FreeHGlobal(IntPtr((void*)chars));它
      • @Pat 是的,对不起,我应该在此之后更新它。我现在确实让它运作良好。将其移至 .NET 使该应用程序的性能提高了 3 倍。甚至整理周围的东西。
      【解决方案5】:

      一个附加链接到可能的方法摘要:

      http://support.microsoft.com/?kbid=311259

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-16
        • 2012-07-26
        相关资源
        最近更新 更多