【问题标题】:Convert a String^ to wstring C++将 String^ 转换为 wstring C++
【发布时间】:2012-12-12 09:56:59
【问题描述】:

我用 C++ 编写了一个小应用程序。 UI 中有一个 ListBox。我想将 ListBox 的选定项用于只能使用 wstrings 的算法。

总而言之,我有两个问题: -我怎样才能转换我的

    String^ curItem = listBox2->SelectedItem->ToString();

到 wstring 测试?

-代码中的^是什么意思?

非常感谢!

【问题讨论】:

  • 这是这个问题的副本:stackoverflow.com/questions/13665649/… 此外,^ 是 C++/CLI 句柄,类似于标准 C++ 中的 * 概念。它称为句柄,表示该对象是一个 .Net 对象。
  • 这是 托管 C++ 又名 C++/CLI 吗?
  • @MauriceReeves 我不认为这是重复的,因为它与转换为 wstring 无关!感谢您提供有关 ^ 的信息
  • @ulidtko 是的,它是一个 C++/CLI 应用程序

标签: string visual-studio-2012 c++-cli wstring


【解决方案1】:

应该很简单:

std::wstring result = msclr::interop::marshal_as<std::wstring>(curItem);

您还需要头文件来完成这项工作:

#include <msclr\marshal.h>
#include <msclr\marshal_cppstd.h>

对于好奇的人来说,这个marshal_as 专业化的内部是什么样子的:

#include <vcclr.h>
pin_ptr<WCHAR> content = PtrToStringChars(curItem);
std::wstring result(content, curItem->Length);

这是因为System::String 在内部存储为宽字符。如果你想要一个std::string,你必须使用例如执行 Unicode 转换。 WideCharToMultiByte。方便marshal_as为您处理所有细节。

【讨论】:

  • 谢谢 Ben Voigt - 我会测试一下 - 给我 5 分钟 :-)
  • 本你能告诉我我从哪里得到 marshal_as 吗?我也包含头文件
  • @user1557170:哎呀,你需要第二个头文件。对此感到抱歉。
  • 我现在有点困惑 - 你能简单地告诉我我需要哪些代码吗?我不是像你这样的专业程序员
  • @Robinson:有两组转换,需要清理的一组需要您创建一个marshal_context 实例,当它超出范围时执行清理。不需要清理的那些(因为它们返回一个智能对象,例如知道如何清理自己的std::string)使用marshal_as。除非您做一些疯狂的事情,例如故意泄漏marshal_context 对象,否则您不会出错。
【解决方案2】:

我将此标记为重复,但这里是关于如何从 System.String^std::string 的答案。

String^ test = L"I am a .Net string of type System::String";
IntPtr ptrToNativeString = Marshal::StringToHGlobalAnsi(test);
char* nativeString = static_cast<char*>(ptrToNativeString.ToPointer());

诀窍是确保您使用互操作和编组,因为您必须跨越从托管代码到非托管代码的边界。

【讨论】:

  • 呸。我拒绝重新发明这个特殊的轮子,特别是因为重新发明使用了错误命名的函数。这里根本没有HGLOBAL。使用该代码是文档的噩梦,因为您必须编写 cmets 来解释非 HGLOBAL 指针实际上是什么。
  • 其实你的回答要好很多。我需要研究 marshal_as 方法。 +1。感谢您指路。
  • 我真的需要一些帮助来消除(嗯,否决)每个建议 StringToHGlobalAnsi 的答案。但这是另一天的工作。
  • 这将是困难的,因为这是甚至微软推荐的此类问题的答案:msdn.microsoft.com/en-us/library/…
  • 那是StringToHGlobalAnsi 页面,他们必须使用该功能。绝不是某个地方的示例表明这是执行任务的最佳方式。
【解决方案3】:

我的版本是:

Platform::String^ str = L"my text";

std::wstring wstring = str->Data();

【讨论】:

  • 我收到error C2039: 'Data' : is not a member of 'System::String'
  • 这项工作在 WinRT 上使用 C++/CX 而不是在旧版 CLR 上使用 C++/CLI
  • 我喜欢这个,因为这是直截了当的:String^ 在 UTF16 中,如果 std::wstring 也应该保留在 UTF16 中 - 不需要转换,只需简单的旧字符副本即可。投票赞成。
【解决方案4】:

使用 Visual Studio 2015,只需执行以下操作:

String^ s = "Bonjour!";

C++/CLI

#include <vcclr.h>
pin_ptr<const wchar_t> ptr = PtrToStringChars(s);

C++/CX

const wchart_t* ptr = s->Data();

【讨论】:

    【解决方案5】:

    根据微软:

    参考How to: Convert System::String to Standard String

    您可以将字符串转换为 std::string 或 std::wstring,而无需在 Vcclr.h 中使用 PtrToStringChars。

    // convert_system_string.cpp
    // compile with: /clr
    #include <string>
    #include <iostream>
    using namespace std;
    using namespace System;
    
    void MarshalString ( String ^ s, string& os ) {
       using namespace Runtime::InteropServices;
       const char* chars =
          (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
       os = chars;
       Marshal::FreeHGlobal(IntPtr((void*)chars));
    }
    
    void MarshalString ( String ^ s, wstring& os ) {
       using namespace Runtime::InteropServices;
       const wchar_t* chars =
          (const wchar_t*)(Marshal::StringToHGlobalUni(s)).ToPointer();
       os = chars;
       Marshal::FreeHGlobal(IntPtr((void*)chars));
    }
    
    int main() {
       string a = "test";
       wstring b = L"test2";
       String ^ c = gcnew String("abcd");
    
       cout << a << endl;
       MarshalString(c, a);
       c = "efgh";
       MarshalString(c, b);
       cout << a << endl;
       wcout << b << endl;
    }
    
    

    输出:

    test
    abcd
    efgh
    

    【讨论】:

      猜你喜欢
      • 2014-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-12
      • 1970-01-01
      • 2011-04-06
      • 2013-02-02
      相关资源
      最近更新 更多