C ++ / CLIによるSystem :: String ^からstd :: stringへの変換


90

誰かが変換する簡単なコードを投稿してください、

System::String^

に、

C ++ std::string

つまり、値を割り当てたいだけです。

String^ originalString;

に、

std::string newString;

回答:


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
この便利なリンクの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はUnicode文字列をstd :: stringのACPに変換します。
マイクリシュケ2015

MSの推奨事項は、marshal_contextを使用し、変換後に削除することです。リンク:msdn.microsoft.com/en-us/library/bb384856.aspx
Ruslan Makrenko

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

これは、質問に直接答える唯一のソリューションです。
ジミニオン2014

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

マーシャル関数を呼び出す必要はありません!

更新エリックのおかげで、バッファオーバーフローを防ぐために入力文字列のサイズをチェックするようにサンプルコードを変更しました。


1
文字列をマーシャルするために特別に設計された関数の呼び出しを回避するためだけに、コードにバッファオーバーフローの脆弱性を導入するのは奇妙な決定です。
Eric

マーシャリング関数を使用したくない場合は、単に別のアプローチを示しています。オーバーフローを防ぐためにサイズのチェックを追加しました。
Ionian316

@Eric内部的にはマーシャリングです。詳細については、このSOの回答を参照してください。事前にサイズを確認しておけば、オーバーフローの問題は発生せず、コードがよりクリーンになります。
Ionian316 2015

4

C#は文字列にUTF16形式を使用します。
したがって、型を変換するだけでなく、文字列の実際の形式についても意識する必要があります。

マルチバイト文字セット用にコンパイルする場合、Visual StudioおよびWin APIはUTF8(実際にはWindowsエンコードであるWindows-28591)を想定しています。Unicode文字セット
用にコンパイルする場合、Visual StudioとWin APIはUTF16を想定しています。

したがって、std :: stringに変換するだけでなく、文字列をUTF16からUTF8形式に変換する必要があります。
これは、一部の非ラテン言語のような複数文字形式で作業するときに必要になります。

アイデアは、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に変換することの重要性を強調したいだけです。Win32OpenFileDialogから受け取ったファイルパス(アジア文字を含むファイル名など、マルチバイト文字が可能なファイル名)をstd経由でエンジンコードに渡す必要がありました。 :: stringなので、UTF8への変換が不可欠でした。すばらしい答えをありがとう!
Jason McClinsey、

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;
        }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.