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.