Каков наилучший способ преобразования между char* и System::String в C++/CLI

Каков утвержденный способ преобразования из char* в System::string и обратно в C++/CLI? Я нашел несколько ссылок на шаблонные функции marshal_to‹> в Google, но, похоже, эта функция никогда не использовалась для Visual Studio 2005 (и, насколько мне известно, ее нет и в Visual Studio 2008). Я также видел некоторый код в блоге Стэна Липпмана, но это с 2004 года. Я также видел Marshal::StringToHGlobalAnsi(). Есть ли метод, который считается «наилучшей практикой»?


person Brian Stewart    schedule 11.09.2008    source источник


Ответы (5)


Здесь есть хороший обзор (эта поддержка маршалинга добавлена ​​для VS2008): http://www.codeproject.com/KB/mcpp/OrcasMarshalAs.aspx

person Matthew Clendening    schedule 11.09.2008
comment
Спасибо, но это длинное объяснение. Это ближе к делу: #include <msclr\marshal.h> // marshal_context context; // my_c_string = context.marshal_as<const char*>(my_csharp_string); - person gatopeich; 08.10.2012
comment
Для тех, кому интересно, полное пространство имен для контекста msclr::interop::marshal_context - person Mugen; 21.02.2018

System::String имеет конструктор, который принимает char*:

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

Вернуть char* немного сложнее, но не так уж плохо:

 IntPtr p = Marshal::StringToHGlobalAnsi(clistr);
 char *pNewCharStr = static_cast<char*>(p.ToPointer());
 cout << pNewCharStr << endl;
 Marshal::FreeHGlobal(p);
person Ben Straub    schedule 11.09.2008
comment
+1, конструктор System::String также принимает длину и кодировку! - person Anthony Serdyukov; 19.04.2010
comment
Marshal::StringToHGlobalAnsi — плохой вариант по сравнению с marshal_context (как упоминал Мэтью), который использует RAII для автоматического освобождения буфера. Не говоря уже о том, что имя совершенно неправильное, оно вообще не возвращает HGLOBAL. - person Ben Voigt; 19.02.2012
comment
Ваш пример не работает для меня в C++/CLI с использованием .NET 4.6.1. Не существует конструктора System::String, который принимает char*... только подписанный char* или wchar_t* - person Dewey Vozel; 15.11.2018
comment
Прошло некоторое время с тех пор, как я был в этом мире, но я верю, что это все еще должно работать. Согласно документам на docs.microsoft.com/en -us/cpp/windows/, вы по-прежнему сможете gcnew использовать строку с char * строкой в ​​качестве аргумента. Может быть, вы можете использовать signed char *? - person Ben Straub; 15.11.2018
comment
По моему опыту, указатель также не имеет нулевого терминатора. Вам нужно использовать clistr.Length, чтобы узнать, какова его длина. - person Menace; 04.11.2020

Что мы сделали, так это создали объект C++\CLI, который содержал строку в неуправляемом коде и выдавал управляемые копии элемента. Код конверсии очень похож на тот, что есть в блоге Стэна (я точно не помню) (если вы используете его код, убедитесь, что вы обновили его, чтобы использовать delete[]), но мы позаботились о том, чтобы деструктор справился с освобождением всех неуправляемые элементы объекта. Это немного преувеличено, но у нас не было утечек, когда мы связывались с устаревшими модулями кода C++.

person Dan Blair    schedule 11.09.2008

Я создал несколько вспомогательных методов. Мне нужно было сделать это, чтобы перейти от старой библиотеки Qt к CLI String. Если кто-нибудь может добавить к этому и сказать мне, похоже ли, что у меня есть утечка памяти и что я могу сделать, чтобы это исправить, я был бы очень признателен.

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;
}
person dko    schedule 01.06.2011
comment
Вероятно, придется Marshal::FreeHGlobal(IntPtr((void*)chars)); Это - person Patrick.SE; 16.04.2012
comment
@ Пэт, да, извини, я должен был обновить это после этого. У меня теперь все хорошо работает. Перенос на .NET повысил производительность этого приложения в 3 раза. Даже упорядочение вещей вокруг. - person dko; 17.04.2012

Одна дополнительная ссылка на сводку возможных способов:

http://support.microsoft.com/?kbid=311259

person Tadej Mali    schedule 25.05.2013