web-dev-qa-db-fra.com

Conversion C++/CLI de System :: String ^ à std :: string

Quelqu'un peut-il s'il vous plaît poster un code simple qui convertirait,

System::String^

À,

C++ std::string

C'est-à-dire que je veux juste assigner la valeur de,

String^ originalString;

À,

std::string newString;
80
sivabudh

Découvrez System::Runtime::InteropServices::Marshal::StringToCoTaskMemUni() et ses amis.

Désolé, je ne peux pas poster de code maintenant; Je n'ai pas de VS sur cette machine pour vérifier si elle est compilée avant de poster.

38
Martin

Ne lancez pas le vôtre, utilisez ceux-ci des wrappers pratiques et extensibles fournis par Microsoft.

Par exemple:

#include <msclr\marshal_cppstd.h>

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

Vous pouvez facilement le faire comme suit

#include <msclr/marshal_cppstd.h>

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

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

Cela a fonctionné pour moi:

#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;
19
Alejandro Perea

Voici quelques routines de conversion que j'ai écrites il y a de nombreuses années pour un projet c ++/cli, elles devraient fonctionnent encore. 

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;
    }
9
Ben Schwehn

J'ai passé des heures à essayer de convertir une valeur ToString d'une liste Windows Forms en une chaîne standard afin de pouvoir l'utiliser avec fstream pour la sortie dans un fichier txt. Mon Visual Studio n’est pas livré avec des fichiers d’en-tête de marshal que plusieurs réponses que j’ai trouvé utilisables Après tant d'essais et d'erreurs, j'ai finalement trouvé une solution au problème utilisant uniquement 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;

Et voici la page MSDN avec l'exemple: http://msdn.Microsoft.com/en-us/library/1b4az623(v=vs.80).aspx

Je sais que c'est une solution assez simple mais cela m'a pris des heures de dépannage et de visiter plusieurs forums pour enfin trouver quelque chose qui a fonctionné.

5
Joe

J'ai trouvé un moyen facile d'obtenir un std :: string à partir d'un String ^, d'utiliser sprintf (). 

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

Pas besoin d'appeler les fonctions Marshal!

UPDATEMerci à Eric, j'ai modifié le code exemple pour vérifier la taille de la chaîne d'entrée afin d'éviter tout débordement de tampon.

4
Ionian316

C # utilise le format UTF16 pour ses chaînes.
Ainsi, en plus de la conversion des types, vous devez également être conscient du format réel de la chaîne.

Lors de la compilation pour le jeu de caractères multi-octets Visual Studio et l'API Win supposent l'UTF8 (En fait, le codage Windows est Windows-28591 ).
Lors de la compilation pour Unicode Jeu de caractères Visual studio et l’API Win supposent UTF16.

Donc, vous devez également convertir la chaîne du format UTF16 au format UTF8, et pas seulement au format std :: string.
Cela deviendra nécessaire lorsque vous travaillerez avec des formats à plusieurs caractères comme certaines langues non latines.

L'idée est de décider que std::wstringalways représente UTF16.
Et std::stringalways représente UTF8

Ceci n'est pas imposé par le compilateur, c'est plutôt une bonne politique à adopter. 

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

Ou avoir une syntaxe plus compacte:

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;
}
3
Yochai Timmer

J'aime rester à l'écart du commissaire.

Using CString newString(originalString);

Cela semble beaucoup plus propre et plus rapide pour moi. Pas besoin de s'inquiéter de la création et de la suppression d'un contexte.

0
LL.

// J'ai utilisé VS2012 pour écrire ci-dessous code-- 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;
        }
0
Praveer Kumar