2008-09-11 9 views
40

¿Cuál es la forma aprobada para convertir de char * a System :: string y viceversa en C++/CLI? Encontré algunas referencias a marshal_to <> funciones con plantilla en Google, pero parece que esta característica nunca hizo el corte para Visual Studio 2005 (y tampoco está en Visual Studio 2008, AFAIK). También he visto un código en Stan Lippman's blog, pero es de 2004. También he visto Marshal :: StringToHGlobalAnsi(). ¿Hay algún método que se considere "mejor práctica"?¿Cuál es la mejor forma de convertir entre char * y System :: String en C++/CLI

Respuesta

18

Hay una buena visión general aquí (este apoyo cálculo de referencias añadido para VS2008): http://www.codeproject.com/KB/mcpp/OrcasMarshalAs.aspx

+7

Gracias, pero eso es una larga explicación. Esto va más al grano: '#include // marshal_context context; // my_c_string = context.marshal_as (my_csharp_string); ' – gatopeich

+0

Para aquellos que se preguntan, el espacio de nombre completo para el contexto es' msclr :: interop :: marshal_context' – Mugen

1

Lo que hicimos se hizo un objeto C++ \ CLI que mantuvo la cadena en código no manipulado y daría copias administradas del elemento. El código de conversión se parece mucho a lo que Stan tiene en su blog (no lo recuerdo exactamente) (Si usa su código, asegúrese de actualizarlo para usar delete []), pero nos aseguramos de que el destructor maneje la liberación de todo los elementos no manejados del objeto. Esto es un poco exagerado, pero no tuvimos filtraciones cuando nos relacionamos con los módulos de código heredados de C++.

70

Sistema :: string tiene un constructor que toma un char *:

using namespace system; 
const char* charstr = "Hello, world!"; 
String^ clistr = gcnew String(charstr); 
Console::WriteLine(clistr); 

Conseguir un char * de vuelta es un poco más difícil, pero no está mal:

IntPtr p = Marshal::StringToHGlobalAnsi(clistr); 
char *pNewCharStr = static_cast<char*>(p.ToPointer()); 
cout << pNewCharStr << endl; 
Marshal::FreeHGlobal(p); 
+4

+1, el constructor System :: String también toma longitud y codificación. –

+5

'Marshal :: StringToHGlobalAnsi' es una opción pobre en comparación con' marshal_context' (como lo menciona Matthew), que utiliza RAII para liberar automáticamente el búfer. Sin mencionar que el nombre es totalmente incorrecto, no devuelve un 'HGLOBAL' en absoluto. –

1

He creado algunos métodos de ayuda. Necesitaba hacer esto para pasar de una antigua biblioteca de Qt a CLI String. Si alguien puede agregar algo sobre esto y decirme si parece que tengo una pérdida de memoria y qué puedo hacer para solucionarlo, lo agradecería mucho.

void MarshalString ( String^s, wstring& os) { 
    using namespace Runtime::InteropServices; 
    const wchar_t* char = (const wchar_t*)(Marshal::StringToHGlobalUni(s)).ToPointer(); 
    os = char; 
} 
QString SystemStringToQt(System::String^ str) 
{ 
    wstring t; 
    MarshalString(str, t); 
    QString r = QString::fromUcs2((const ushort*)t.c_str()); 
    return r; 
} 
+0

Probablemente tenga que Marshal :: FreeHGlobal (IntPtr ((void *) caracteres)); es –

+0

@Pat sí, lo siento, debería haberlo actualizado después de esto. Lo hice funcionar bien ahora. Moverlo a .NET aumentó el rendimiento de esta aplicación en 3x. Incluso clasificando cosas alrededor. – dko

Cuestiones relacionadas