C ++ / CLI System :: String ^에서 std :: string으로 변환


91

누군가 변환 할 간단한 코드를 게시 해 주시겠습니까?

System::String^

에,

C ++ std::string

즉, 값을 할당하고 싶습니다.

String^ originalString;

에,

std::string newString;

답변:


38

확인 System::Runtime::InteropServices::Marshal::StringToCoTaskMemUni()하고 그 친구들.

지금 코드를 게시 할 수 없습니다. 게시하기 전에 컴파일을 확인하기 위해이 컴퓨터에 VS가 없습니다.


162

자신의 롤하지 마십시오, 사용 이 Microsoft에서 제공하는 편리 (및 확장) 래퍼.

예를 들면 :

#include <msclr\marshal_cppstd.h>

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

2
이 유용한 링크에 대한 thx,이 힌트는 많은 코딩을 절약했습니다. 참고 : 템플릿 / 클래스는 #include <msclr \ *. h> (예 : #include <msclr \ marshal.h>) 및 msclr :: interop 네임 스페이스에 있습니다. msdn.microsoft.com 의 예제를 참조 하십시오. /de-de/library/vstudio/bb384859(v=vs.90).aspx )
— Beachwalker

4
이것은 편리하지만 적절한 인코딩 지원이 완전히 부족합니다. 내 SO 질문 참조 : stackoverflow.com/questions/18894551/… . 내 가정은 marshal_as가 유니 코드 문자열을 std :: string의 ACP로 변환한다는 것입니다.
— Mike Lischke

MS 권장 사항은 marshal_context를 사용하고 변환이 완료된 후 삭제하는 것입니다. 링크 : msdn.microsoft.com/en-us/library/bb384856.aspx
— Ruslan

40

다음과 같이 쉽게 할 수 있습니다.

#include <msclr/marshal_cppstd.h>

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

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

짧고 간단한 솔루션 및 간단한 작업, 예를 들어 1 (추가 괄호는 코드의 끝 부분에있다하더라도)
— 사이먼 포스 버그

이것은 질문에 직접 답하는 유일한 해결책입니다.
— Jiminion 2014-06-06

8
흠 ... 거의 같은 줄의 코드로 이미 2 년 전에 제공된 답변에 대해 33 개의 찬성 투표를했습니다. 그것에 대해 많은 점수를 얻은 것에 대한 존경. ;-)
— 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를 사용하여 작성 합니다. .
— neo

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

나는 그것이 매우 간단한 해결책이라는 것을 알고 있지만 마침내 작동하는 것을 찾기 위해 문제를 해결하고 여러 포럼을 방문하는 데 몇 시간이 걸렸습니다.


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

Marshal 함수를 호출 할 필요가 없습니다!

업데이트 Eric 덕분에 버퍼 오버플로를 방지하기 위해 입력 문자열의 크기를 확인하도록 샘플 코드를 수정했습니다.


1
문자열을 마샬링하도록 특별히 설계된 함수를 호출하지 않기 위해 코드에 버퍼 오버플로 취약점을 도입하는 것은 흥미로운 결정입니다.
— 에릭

누군가 마샬 기능을 사용하지 않으려는 경우 다른 접근 방식을 제시하고 있습니다. 오버플로를 방지하기 위해 크기 확인을 추가했습니다.
— Ionian316 2015 년

@Eric 내부적으로 그것은 당신을 위해 마샬링입니다. 자세한 내용은 이 SO 답변 을 참조하십시오. 미리 크기를 확인하면 오버플로 문제가 발생하지 않고 코드가 훨씬 깔끔해집니다.
— Ionian316

4

C #은 문자열에 UTF16 형식을 사용합니다.
따라서 유형을 변환하는 것 외에도 문자열의 실제 형식에 대해서도 알고 있어야합니다.

멀티 바이트 문자 집합을 컴파일 할 때 Visual Studio 및 Win API는 UTF8 (실제로 Windows-28591 인 Windows 인코딩)을 가정합니다 . 유니 코드 문자 집합
용으로 컴파일 할 때 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로 변환하는 것의 중요성을 강조하고 싶습니다. Win32 OpenFileDialog (멀티 바이트 문자가있는 파일 이름, 예를 들어 아시아 문자가 포함 된 파일 이름)에서받은 파일 경로를 std를 통해 엔진 코드로 전달해야했습니다. :: string이므로 UTF8 로의 변환이 중요했습니다. 훌륭한 답변에 감사드립니다!
— Jason McClinsey 19 년

0

나는 마샬 러에게서 떨어져있는 것을 좋아합니다.

Using CString newString(originalString);

나에게 훨씬 깨끗하고 빠르다. 컨텍스트 생성 및 삭제에 대해 걱정할 필요가 없습니다.


0

// VS2012를 사용하여 아래 코드를 작성했습니다. convert_system_string to 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;
        }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.