2009-08-19 28 views
46

¿Cómo se convierte System :: String en std :: string en C++ .NET?C++ .NET convert System :: String to std :: string

+5

. Convierte a std :: wstring. System.String es Unicode, no ASCII – MSalters

+6

@MSalters Huh? Parece que tiene la impresión de que la conversión no incluye la traducción o que todos pueden elegir las API con las que van a interactuar ... –

Respuesta

55

No es la sintaxis más limpia si está utilizando una versión reciente 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; 
} 

Esto también le da una mejor limpieza en la cara de excepciones.

Hay un msdn article para varias otras conversiones

+0

¿Esto también se ocupa de la codificación de UTF-16 (valor predeterminado de .Net) a 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

Esta es la sintaxis anterior. Prefiero el que sugirió Colin arriba. – orad

+0

¿Qué pasa si arroja sstr()? ¿Eso no causaría que cstr se convirtiera en una filtración? –

25

y en respuesta a la "manera fácil" en versiones posteriores de C++/CLI, puede hacerlo sin la marshal_context. Sé que esto funciona en Visual Studio 2010; no estoy seguro antes de eso.


#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

Mire el artículo de MSDN al que Collin se vinculó para ver cuándo usar marshal_as y cuándo usar el contexto marshal_context. En general, el contexto marshal_ es necesario cuando los recursos no administrados deben limpiarse. – rotti2

+2

El artículo dice que uno solo necesita un contexto si el tipo nativo no tiene un destructor para hacer su propia limpieza. Entonces, en el caso de 'std :: string', ¿es esto necesario? –

+1

El contexto no es necesario para 'std :: string'. El contexto solo es necesario cuando se hace una clasificación desde un tipo envuelto a un tipo no envuelto (es decir, un puntero sin formato). Como se detalla en [Descripción general de Marshaling en C++] (http://msdn.microsoft.com/en-us/library/bb384865.aspx), solo hay tres instancias donde se necesita el contexto. –

3

que tenía demasiados errores ambiguos a aparecer con las respuestas anteriores (sí, soy un C++ novato)

Esto funcionó para mí para el envío de cadena de C# para C++ CLI

C#

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

C++ CLI

función:

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

función que trabaja a partir de la conversión de cadena^a 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; 
} 

EN nuevas investigaciones, parece que esto es más limpio y más seguro.

Cambié a utilizar este método en su lugar.

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

Entonces, ¿cómo se las arregló para deshacerse de todos los errores de ambigüedad de IServiceProvider? –

+0

No recuerdo haber recibido esos errores. Era nuevo en C++, ahora estoy en otro contrato/proyecto con otra compañía ... lo siento mucha suerte. –

0

Creación de un tiempo de ejecución de componentes de Windows que puede utilizar:

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

C# utiliza el formato UTF16 por sus cadenas.
Por lo tanto, además de convertir los tipos, también debe ser consciente del formato real de la cadena.

cuando se compila para caracteres multi-byte conjunto Visual Studio y la API Win asume UTF8 (En realidad codificación ventanas que es Windows-28591).
Al compilar para Conjunto de caracteres Unicode Visual Studio y la API de Windows asumen UTF16.

Por lo tanto, también debe convertir la cadena de UTF16 a formato UTF8, y no solo convertir a std :: string.
Esto será necesario cuando trabaje con formatos de caracteres múltiples, como algunos idiomas no latinos.

La idea es decidir que std::wstringsiempre representa UTF16.
Y std::stringsiempre representa UTF8.

Esto no se aplica por el compilador, es más una buena política que tener.

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

o lo tiene en una sintaxis más compacta:

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