C ++ / CLI从System :: String ^转换为std :: string


90

有人可以张贴一个简单的代码进行转换,

System::String^

至,

C ++ std::string

即,我只想分配的值,

String^ originalString;

至,

std::string newString;

Answers:


38

退房System::Runtime::InteropServices::Marshal::StringToCoTaskMemUni()及其朋友。

抱歉,现在无法发布代码;我在这台机器上没有VS,可以在发布前检查其编译情况。


159

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

例如:

#include <msclr\marshal_cppstd.h>

System::String^ managed = "test";
std::string unmanaged = msclr::interop::marshal_as<std::string>(managed);

2
对于这个有用的链接,此提示为我节省了很多代码。附带说明:模板/类在#include <msclr \ *。h>中(例如#include <msclr \ marshal.h>)和msclr :: interop命名空间中,请参见msdn.microsoft.com上的示例/de-de/library/vstudio/bb384859(v=vs.90).aspx
海滩漫步

4
尽管这很方便,但它完全缺少适当的编码支持。另请参阅我的SO问题:stackoverflow.com/questions/18894551/…。我的假设是marshal_as将Unicode字符串转换为std :: string中的ACP。
Mike Lischke,2015年

MS建议使用marshal_context并在转换完成后将其删除。链接:msdn.microsoft.com/en-us/library/bb384856.aspx
Ruslan Makrenko '18年

40

您可以按照以下步骤轻松地执行此操作

#include <msclr/marshal_cppstd.h>

System::String^ xyz="Hi boys"; 

std::string converted_xyz=msclr::interop::marshal_as< std::string >( xyz);

+1是一个简短而简单的解决方案和简单的工作示例(尽管您的代码末尾有一个括号)
Simon Forsberg 2012年

这是直接回答问题的唯一解决方案。
Jiminion 2014年

8
嗯... 33票赞成2年前就已经用几乎相同的代码行给出的答案。尊重为此获得许多积分。;-)
Beachwalker

20

这为我工作:

#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;

3
英文翻译:“我也将回复此帖子:p。这是我的职责。”
sivabudh 2010年

9

下面是我很多年前写的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使用命名空间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/zh-cn/library/1b4az623(v=vs.80).aspx

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


6

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

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

无需调用元帅功能!

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


1
为了避免调用专门设计用于编组字符串的函数,在代码中引入缓冲区溢出漏洞是一个奇怪的决定。
埃里克

如果有人不想使用封送功能,我只是提出一种不同的方法。我添加了尺寸检查以防止溢出。
Ionian316 2015年

@Eric内部正在为您编组。有关详细信息,请参见此SO答案。如果事先检查大小,将不会有任何溢出问题,并且代码更简洁。
Ionian316

4

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

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

因此,您还必须将字符串也从UTF16转换为UTF8格式,而不仅仅是转换为std :: string。
当使用诸如非拉丁语言的多字符格式时,这将变得必要。

想法是确定std::wstring 始终代表UTF16
std::string 始终代表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;
}

1
我只想强调在用例中转换为UTF8的重要性:我需要通过std将从Win32 OpenFileDialog接收到的文件路径(可以使用多字节字符的文件名,例如包含亚洲字符的文件名)传递给引擎代码。 :: string,因此转换为UTF8至关重要。感谢您的出色回答!
杰森·麦克林西

0

我喜欢远离编组人员。

Using CString newString(originalString);

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


0

//我用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;
        }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.