Как лучше всего конвертировать между char * и System :: String в C++ / CLI

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
44
0
65 936
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

Ответ принят как подходящий

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

Спасибо, но это длинное объяснение. Это ближе к делу: #include <msclr\marshal.h> // marshal_context context; // my_c_string = context.marshal_as<const char*>(my_csharp_string);

gatopeich 08.10.2012 20:07

Для тех, кому интересно, полное пространство имен для контекста - msclr::interop::marshal_context.

Mugen 21.02.2018 18:51

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

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

+1, конструктор System :: String также принимает длину и кодировку!

Anthony Serdyukov 19.04.2010 15:53

Marshal::StringToHGlobalAnsi - плохой вариант по сравнению с marshal_context (как упоминал Мэтью), который использует RAII для автоматического освобождения буфера. Не говоря уже о том, что название полностью неправильное, оно вообще не возвращает HGLOBAL.

Ben Voigt 19.02.2012 22:09

Ваш пример не работает для меня в C++ / CLI с использованием .NET 4.6.1. Не существует конструктора System :: String, который принимает char * ... только подписанный char * или wchar_t *

Dewey Vozel 15.11.2018 17:39

Я давно не был в этом мире, но я считаю, что это все еще должно работать. Согласно документации на docs.microsoft.com/en-us/cpp/windows/…, вы все равно должны иметь возможность gcnew для строки со строкой char * в качестве аргумента. Может можно на signed char * закинуть?

Ben Straub 15.11.2018 21:26

По моему опыту, указатель также не имеет нулевого терминатора. Вам нужно использовать cluster.Length, чтобы узнать, сколько он длится.

Menace 04.11.2020 20:06

Я создал несколько вспомогательных методов. Мне нужно было сделать это, чтобы перейти от старой библиотеки 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;
}

Наверное придется Marshal :: FreeHGlobal (IntPtr ((void *) chars)); Это

Patrick.SE 16.04.2012 18:45

@Pat да, извините, я должен был обновить это после этого. Теперь у меня все получилось. Перенос его на .NET увеличил производительность этого приложения в 3 раза. Даже упорядочивание вещей.

dko 17.04.2012 19:11

Еще одна ссылка на список возможных способов:

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

Другие вопросы по теме