【问题标题】:C++/CLI Converting from System::String^ to std::stringC++/CLI 从 System::String^ 转换为 std::string
【发布时间】:2009-06-03 19:51:10
【问题描述】:

有人可以发布一个可以转换的简单代码,

System::String^

到,

C++std::string

即,我只想分配的值,

String^ originalString;

到,

std::string newString;

【问题讨论】:

    标签: string c++-cli managed-c++


    【解决方案1】:

    不要自己动手,使用 Microsoft 提供的方便(且可扩展)的包装器 these

    例如:

    #include <msclr\marshal_cppstd.h>
    
    System::String^ managed = "test";
    std::string unmanaged = msclr::interop::marshal_as<std::string>(managed);
    

    【讨论】:

    【解决方案2】:

    你可以很容易地做到这一点

    #include <msclr/marshal_cppstd.h>
    
    System::String^ xyz="Hi boys"; 
    
    std::string converted_xyz=msclr::interop::marshal_as< std::string >( xyz);
    

    【讨论】:

    • +1 是一个简短的解决方案和简单的工作示例(尽管代码末尾有一个额外的括号)
    • 这是唯一直接回答问题的解决方案。
    • hmm... 33 人赞成 2 年多前已经用几乎相同的代码行给出的答案。尊重为此获得了这么多积分。 ;-)
    【解决方案3】:

    查看System::Runtime::InteropServices::Marshal::StringToCoTaskMemUni() 及其朋友。

    抱歉,现在无法发布代码;我在这台机器上没有 VS 在发布前检查它是否编译。

    【讨论】:

      【解决方案4】:

      这对我有用:

      #include <stdlib.h>
      #include <string.h>
      #include <msclr\marshal_cppstd.h>
      //..
      using namespace msclr::interop;
      //..
      System::String^ clrString = (TextoDeBoton);
      std::string stdString = marshal_as<std::string>(clrString); //String^ to std
      //System::String^ myString = marshal_as<System::String^>(MyBasicStirng); //std to String^
      prueba.CopyInfo(stdString); //MyMethod
      //..
      //Where: String^ = TextoDeBoton;
      //and stdString is a "normal" string;
      

      【讨论】:

      • 英文翻译:“我也要回复这篇文章:p。这是我的职责。”
      【解决方案5】:

      这是我多年前为一个 c++/cli 项目编写的一些转换例程,它们应该仍然有效。

      void StringToStlWString ( System::String const^ s, std::wstring& os)
          {
              String^ string = const_cast<String^>(s);
              const wchar_t* chars = reinterpret_cast<const wchar_t*>((Marshal::StringToHGlobalUni(string)).ToPointer());
              os = chars;
              Marshal::FreeHGlobal(IntPtr((void*)chars));
      
          }
          System::String^ StlWStringToString (std::wstring const& os) {
              String^ str = gcnew String(os.c_str());
              //String^ str = gcnew String("");
              return str;
          }
      
          System::String^ WPtrToString(wchar_t const* pData, int length) {
              if (length == 0) {
                  //use null termination
                  length = wcslen(pData);
                  if (length == 0) {
                      System::String^ ret = "";
                      return ret;
                  }
              }
      
              System::IntPtr bfr = System::IntPtr(const_cast<wchar_t*>(pData));
              System::String^ ret = System::Runtime::InteropServices::Marshal::PtrToStringUni(bfr, length);
              return ret;
          }
      
          void Utf8ToStlWString(char const* pUtfString, std::wstring& stlString) {
              //wchar_t* pString;
              MAKE_WIDEPTR_FROMUTF8(pString, pUtfString);
              stlString = pString;
          }
      
          void Utf8ToStlWStringN(char const* pUtfString, std::wstring& stlString, ULONG length) {
              //wchar_t* pString;
              MAKE_WIDEPTR_FROMUTF8N(pString, pUtfString, length);
              stlString = pString;
          }
      

      【讨论】:

      • @alap,使用 System::Runtime::InteropServices::Marshal 或编写 using namespace System::Runtime::InteropServices;
      【解决方案6】:

      我花了几个小时尝试将 Windows 表单列表框的 ToString 值转换为标准字符串,以便可以将其与 fstream 一起使用以输出到 txt 文件。我的 Visual Studio 没有附带我发现的几个答案说要使用的编组头文件。经过这么多的试验和错误,我终于找到了解决问题的方法,只使用 System::Runtime::InteropServices:

      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));
      }
      
      //this is the code to use the function:
      scheduleBox->SetSelected(0,true);
      string a = "test";
      String ^ c = gcnew String(scheduleBox->SelectedItem->ToString());
      MarshalString(c, a);
      filestream << a;
      

      这是带有示例的 MSDN 页面: http://msdn.microsoft.com/en-us/library/1b4az623(v=vs.80).aspx

      我知道这是一个非常简单的解决方案,但这花了我数小时的时间进行故障排除并访问了几个论坛,最终找到了可行的方法。

      【讨论】:

        【解决方案7】:

        我发现从 String^ 获取 std::string 的简单方法是使用 sprintf()。

        char cStr[50] = { 0 };
        String^ clrString = "Hello";
        if (clrString->Length < sizeof(cStr))
          sprintf(cStr, "%s", clrString);
        std::string stlString(cStr);
        

        无需调用 Marshal 函数!

        更新感谢 Eric,我修改了示例代码以检查输入字符串的大小以防止缓冲区溢出。

        【讨论】:

        • 在代码中引入缓冲区溢出漏洞是一个奇怪的决定,只是为了避免调用专门设计用于编组字符串的函数。
        • 如果有人不想使用 marshal 函数,我只是提出了一种不同的方法。我添加了大小检查以防止溢出。
        • @Eric 在内部它正在为您编组。有关详细信息,请参阅this SO answer。如果事先检查大小,就不会出现溢出问题,代码也更干净。
        【解决方案8】:

        C# 对其字符串使用 UTF16 格式。
        因此,除了转换类型之外,您还应该注意字符串的实际格式。

        当为多字节字符集编译时,Visual Studio 和 Win API 假定为 UTF8(实际上 windows 编码是 Windows-28591)。
        Unicode 字符集编译时,Visual Studio 和 Win API 假定为 UTF16。

        因此,您还必须将字符串从 UTF16 转换为 UTF8 格式,而不仅仅是转换为 std::string。
        这在处理多字符格式(如某些非拉丁语言)时将变得很有必要。

        这个想法是确定std::wstring always 代表 UTF16
        std::string always 代表 UTF8

        这不是由编译器强制执行的,它更像是一个好的策略。

        #include "stdafx.h"
        #include <string>
        #include <codecvt>
        #include <msclr\marshal_cppstd.h>
        
        using namespace System;
        
        int main(array<System::String ^> ^args)
        {
            System::String^ managedString = "test";
        
            msclr::interop::marshal_context context;
        
            //Actual format is UTF16, so represent as wstring
            std::wstring utf16NativeString = context.marshal_as<std::wstring>(managedString); 
        
            //C++11 format converter
            std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;
        
            //convert to UTF8 and std::string
            std::string utf8NativeString = convert.to_bytes(utf16NativeString);
        
            return 0;
        }
        

        或者使用更紧凑的语法:

        int main(array<System::String ^> ^args)
        {
            System::String^ managedString = "test";
        
            msclr::interop::marshal_context context;
            std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;
        
            std::string utf8NativeString = convert.to_bytes(context.marshal_as<std::wstring>(managedString));
        
            return 0;
        }
        

        【讨论】:

        • 我只想强调在我的用例中转换为 UTF8 的重要性:我需要传递从 Win32 OpenFileDialog 接收的文件路径(其中可以使用多字节字符的文件名,例如包含亚洲的文件名个字符)通过 std::string 转换为引擎代码,因此转换为 UTF8 至关重要。感谢您的出色回答!
        【解决方案9】:

        我喜欢远离编组器。

        Using CString newString(originalString);
        

        对我来说似乎更干净、更快捷。无需担心创建和删除上下文。

        【讨论】:

          【解决方案10】:

          //我用VS2012写了下面的代码--convert_system_string到Standard_Sting

                  #include "stdafx.h"
                  #include <iostream>
                  #include <string> 
          
                  using namespace System;
                  using namespace Runtime::InteropServices; 
          
          
                  void MarshalString ( String^ s, std::string& outputstring )
                  {  
                     const char* kPtoC =  (const char*) (Marshal::StringToHGlobalAnsi(s)).ToPointer();                                                        
                     outputstring = kPtoC;  
                     Marshal::FreeHGlobal(IntPtr((void*)kPtoC));  
                  }   
          
                  int _tmain(int argc, _TCHAR* argv[])
                  {
                       std::string strNativeString;  
                       String ^ strManagedString = "Temp";
          
                       MarshalString(strManagedString, strNativeString);  
                       std::cout << strNativeString << std::endl; 
          
                       return 0;
                  }
          

          【讨论】:

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