2009-08-19 4 views
46

Wie konvertiert man System :: String zu std :: string in C++ .NET?C++ .NET konvertieren System :: String in std :: string

+5

Nicht. In std :: wstring konvertieren. System.String ist Unicode, nicht ASCII – MSalters

+6

@MSalters Huh? Sie scheinen den Eindruck zu haben, dass die Konvertierung keine Übersetzung enthält oder dass jeder immer auswählen kann, mit welchen APIs er interagieren wird ... –

Antwort

55

Es ist saubere Syntax, wenn Sie eine aktuelle Version von .NET sind

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

Dies gibt Ihnen auch besser clean-up im Gesicht von Ausnahmen.

Es gibt eine msdn article für verschiedene andere Umwandlungen

+0

Wird dabei auch die Codierung von UTF-16 (.Net-Standard) nach UTF-8 (Std :: String) beachtet? – 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

Dies ist die ältere Syntax. Ich bevorzuge den, den Colin oben vorgeschlagen hat. – orad

+0

Was passiert, wenn sstr() wirft? Würde das nicht dazu führen, dass cstr zu einem Leck wird? –

25

Und als Reaktion auf den „einfacheren Weg“ in späteren Versionen von C++/CLI, können Sie es ohne den marshal_context zu tun. Ich weiß, das funktioniert in Visual Studio 2010; vorher nicht sicher.


#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

Sehen Sie sich den MSDN-Artikel Collin an, um zu sehen, wann marschall_as zu verwenden ist und wann marschall_kontext verwendet werden soll. Im Allgemeinen wird der Marshal_context benötigt, wenn nicht gemanagte Ressourcen bereinigt werden müssen. – rotti2

+2

Der Artikel sagt, dass man nur einen Kontext benötigt, wenn der native Typ keinen Destruktor hat, um seine eigene Bereinigung durchzuführen. Also, im Falle von 'std :: string', wird das benötigt? –

+1

Der Kontext wird nicht für 'std :: string' benötigt. Der Kontext wird nur benötigt, wenn von einem umhüllten Typ zu einem unverpackten Typ (d. H. Roher Zeiger) marshaliert wird. Wie in [Überblick über Marshalling in C++] (http://msdn.microsoft.com/en-us/library/bb384865.aspx) aufgeführt, gibt es nur drei Instanzen, in denen der Kontext benötigt wird. –

3

Ich hatte zu viele mehrdeutige Fehler mit den oben genannten Antworten zeigt sich (ja, ich bin ein C++ Noob)

Das ist für mich gearbeitet Zeichenfolge von C# C für das Senden ++ CLI

C#

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

C++ CLI

Funktion:

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

Funktion, die aus der Umwandlung String^arbeitet 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; 
} 

AUF WEITERE RESEARCH, es scheint, dass diese sauberer und sicherer ist.

Ich wechselte zu dieser Methode stattdessen.

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

Wie haben Sie es geschafft, alle IServiceProvider-Mehrdeutigkeitsfehler zu beseitigen? –

+0

Ich erinnere mich nicht, diese Fehler zu bekommen. Ich war neu in C++, jetzt bin ich auf einem anderen Vertrag/Projekt mit einer anderen Firma .... Entschuldigung, viel Glück. –

0

eine Windows-Runtime-Komponente Erstellen Sie verwenden können:

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

C# verwendet das UTF16-Format für die Saiten.
Neben der Konvertierung der Typen sollten Sie sich also auch des tatsächlichen Formats der Zeichenfolge bewusst sein.

Beim Kompilieren für Multi-Byte-Zeichensatz Visual Studio und die Win-API nimmt UTF8 (eigentlich Windows-Codierung, die Windows-28591 ist).
Beim Kompilieren für Unicode-Zeichensatz Visual Studio und die Win-API nehmen UTF16 an.

Also müssen Sie die Zeichenfolge von UTF16 in UTF8 Format konvertieren, und nicht nur in std :: string konvertieren.
Dies wird notwendig, wenn Sie mit Multi-Character-Formaten wie einigen nicht-lateinischen Sprachen arbeiten.

Die Idee ist, zu entscheiden, dass std::wstringimmerUTF16 darstellt.
Und std::stringimmer steht für UTF8.

Dies wird nicht vom Compiler erzwungen, es ist mehr eine gute Richtlinie zu haben.

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

Oder haben es in einer kompakteren Syntax:

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