2009-08-19 6 views
46

Comment convertir System :: String en std :: string en C++ .NET?C++ .NET convertir System :: String en std :: string

+5

Ne pas. Convertir en std :: wstring. System.String est Unicode, pas ASCII – MSalters

+6

@MSalters Huh? Vous semblez avoir l'impression que la conversion n'inclut pas la traduction ou que tout le monde peut toujours choisir l'API avec laquelle ils vont interagir ... –

Répondre

55

Il est plus propre syntaxe si vous utilisez une version récente de .net

#include "stdafx.h" 
#include <string> 

#include <msclr\marshal_cppstd.h> 

using namespace System; 

int main(array<System::String ^> ^args) 
{ 
    System::String^ managedString = "test"; 

    msclr::interop::marshal_context context; 
    std::string standardString = context.marshal_as<std::string>(managedString); 

    return 0; 
} 

Cela vous donne également mieux nettoyage face à des exceptions.

Il y a un msdn article pour diverses autres conversions

+0

Est-ce que cela prend également en charge le codage de UTF-16 (par défaut .Net) à UTF-8 (std :: string)? – zak

7
stdString = toss(systemString); 

    static std::string toss(System::String^s) 
    { 
    // convert .NET System::String to std::string 
    const char* cstr = (const char*) (Marshal::StringToHGlobalAnsi(s)).ToPointer(); 
    std::string sstr = cstr; 
    Marshal::FreeHGlobal(System::IntPtr((void*)cstr)); 
    return sstr; 
    } 
+1

C'est la syntaxe la plus ancienne. Je préfère celui que Colin a suggéré ci-dessus. – orad

+0

Que faire si sstr() lance? Cela ne ferait-il pas de cstr une fuite? –

25

Et en réponse à la « manière plus facile » dans les versions ultérieures de C++/CLI, vous pouvez le faire sans marshal_context. Je sais que cela fonctionne dans Visual Studio 2010; pas sûr d'avant cela.


#include "stdafx.h" 
#include <string> 

#include <msclr\marshal_cppstd.h> 

using namespace msclr::interop; 

int main(array<System::String ^> ^args) 
{ 
    System::String^ managedString = "test"; 

    std::string standardString = marshal_as<std::string>(managedString); 

    return 0; 
} 

+1

Regardez l'article MSDN Collin lié pour voir quand utiliser marshal_as et quand utiliser marshal_context. En règle générale, marshal_context est nécessaire lorsque des ressources non managées doivent être nettoyées. – rotti2

+2

L'article dit qu'il suffit d'un contexte si le type natif n'a pas de destructeur pour effectuer son propre nettoyage. Donc, dans le cas de 'std :: string', est-ce nécessaire? –

+1

Le contexte n'est pas nécessaire pour 'std :: string'. Le contexte n'est nécessaire que lors du marshaling d'un type enveloppé vers un type non enveloppé (c'est-à-dire un pointeur brut). Comme indiqué dans [Présentation de Marshaling en C++] (http://msdn.microsoft.com/en-us/library/bb384865.aspx), il n'y a que trois instances où le contexte est nécessaire. –

3

J'ai eu trop d'erreurs ambiguës montrant les réponses ci-dessus (oui, je suis un C++ Noob)

Cela a fonctionné pour moi pour envoyer la chaîne de C# à C++ CLI

C#

bool result; 
result = mps.Import(mpsToolName); 

C++ CLI

Fonction:

bool ManagedMPS::Import(System::String^ mpsToolNameTest) 
std::string mpsToolName; 
mpsToolName = toStandardString(mpsToolNameTest); 
fonction

qui fonctionne de la conversion String^à std :: string

static std::string toStandardString(System::String^ string) 
{ 
using System::Runtime::InteropServices::Marshal; 
System::IntPtr pointer = Marshal::StringToHGlobalAnsi(string); 
char* charPointer = reinterpret_cast<char*>(pointer.ToPointer()); 
std::string returnString(charPointer, string->Length); 
Marshal::FreeHGlobal(pointer); 
return returnString; 
} 

SUR LA RECHERCHE DE PLUS, il semble que ce soit plus propre et plus sûr. J'ai changé pour utiliser cette méthode à la place.

std::string Utils::ToUnmanagedString(String^ stringIncoming) 
{ 
    std::string unmanagedString = marshal_as<std::string>(stringIncoming); 
    return unmanagedString; 
} 
+0

Alors, comment avez-vous réussi à vous débarrasser de toutes les erreurs d'ambiguïté IServiceProvider? –

+0

Je ne me souviens pas d'avoir eu ces erreurs. J'étais nouveau au C++, maintenant je suis sur un autre contrat/projet avec une compagnie différente .... désolé bonne chance. –

0

Création d'un composant Windows Runtime vous pouvez utiliser:

String^ systemString = "Hello"; 
std::wstring ws1(systemString ->Data()); 
std::string standardString(ws1.begin(), ws1.end()); 
6

C# utilise le format UTF16 pour ses cordes.
Donc, en plus de simplement convertir les types, vous devez également être conscient du format réel de la chaîne.

Lors de la compilation pour Jeu de caractères codés sur plusieurs octets Visual Studio et l'API Win supposent 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. Par conséquent, vous devez également convertir la chaîne du format UTF16 au format UTF8, et pas seulement convertir en chaîne std :: string.
Cela devient nécessaire lorsque vous travaillez avec des formats multi-caractères comme certaines langues non-latin.

L'idée est de décider que std::wstringtoujours représente UTF16.
et std::stringtoujours représente UTF8.

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

#include "stdafx.h" 
#include <string> 

#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 ont dans 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; 
} 
Questions connexes