将 String^ 转换为 wstring C++

Posted

技术标签:

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

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

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

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

到 wstring 测试?

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

非常感谢!

【问题讨论】:

这是这个问题的副本:***.com/questions/13665649/… 此外,^ 是 C++/CLI 句柄,类似于标准 C++ 中的 * 概念。它称为句柄,表示该对象是一个 .Net 对象。 这是 托管 C++ 又名 C++/CLI 吗? @MauriceReeves 我不认为这是重复的,因为它与转换为 wstring 无关!感谢您提供有关 ^ 的信息 @ulidtko 是的,它是一个 C++/CLI 应用程序 Need to convert String^ to char *的可能重复 【参考方案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

【讨论】:

以上是关于将 String^ 转换为 wstring C++的主要内容,如果未能解决你的问题,请参考以下文章

将 String^ 转换为 wstring C++

C++ 使用最少的代码将字符串转换为 wstring 并返回

C++ 将 wstring 转换为 Unicode

将 std::string 转换为 std::wstring 时,C++17 codecvt 抛出“错误转换”

如何将 UTF-8 std::string 转换为 UTF-16 std::wstring?

C++ .NET 将 System::String 转换为 std::string