Как конвертировать Platform::String в char*?

Как мне преобразовать содержимое Platform::String для использования функциями, которые ожидают строку на основе char*? Я предполагаю, что WinRT предоставляет вспомогательные функции для этого, но я просто не могу их найти.

Спасибо!

6 ответов

Решение

Platform::String::Data() вернет wchar_t const* указывая на содержимое строки (аналогично std::wstring::c_str()). Platform::String представляет собой неизменяемую строку, поэтому нет средства доступа для получения wchar_t*, Вам нужно будет скопировать его содержимое, например, в std::wstring, чтобы внести изменения.

Там нет прямого способа получить char* или char const* так как Platform::String использует широкие символы (все приложения в стиле Metro являются приложениями Unicode). Вы можете преобразовать в многобайтовый, используя WideCharToMultiByte,

Вот очень простой способ сделать это в коде без необходимости беспокоиться о длине буфера. Используйте это решение, только если вы уверены, что имеете дело с ASCII:

Platform::String^ fooRT = "aoeu";
std::wstring fooW(fooRT->Begin());
std::string fooA(fooW.begin(), fooW.end());
const char* charStr = fooA.c_str();

Имейте в виду, что в этом примере char* находится в стеке и уйдет, как только он покинет область

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

#include <cvt/wstring>
#include <codecvt>

Platform::String^ fooRT = "foo";
stdext::cvt::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
std::string stringUtf8 = convert.to_bytes(fooRT->Data());
const char* rawCstring = stringUtf8.c_str();

Там есть String::Data метод возврата const char16*, которая является необработанной строкой Unicode.

Преобразование из Unicode в ASCII или что-то, т. Е. char16* в char*Это другое дело. Вы, вероятно, не нуждаетесь в этом, так как большинство методов имеют свои wchar версии в эти дни.

Решение с использованием wcstombs:

Platform::String^ platform_string = p_e->Uri->AbsoluteUri;
const wchar_t* wide_chars =  platform_string->Data();
char chars[512];
wcstombs(chars, wide_chars, 512);

Решение 1:

      #include <cvt/wstring>
#include <codecvt>

Platform::String^ tTextRT = "TestText";
stdext::cvt::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
std::string stringUtf8 = convert.to_bytes(tTextRT->Data());
const char* rawCstring = stringUtf8.c_str();

Но это решение генерирует ошибку.

Ошибка C4996 'stdext::cvt': предупреждение STL4044: Содержимое пространства имен stdext::cvt не является стандартным расширением и будет удалено в будущем. Вместо этого можно использовать функции MultiByteToWideChar() и WideCharToMultiByte(). Вы можете определить _SILENCE_STDEXT_CVT_DEPRECATION_WARNING или _SILENCE_ALL_MS_EXT_DEPRECATION_WARNINGS для подавления этого предупреждения.

Решение 2:

      Platform::String^ testText = "Test Text";
std::wstring tTextW(testText->Begin());
std::string tTextA(tTextW.begin(), tTextW.end());
const char* charStr = tTextA.c_str();

Но у этого решения есть еще одна проблема:

Любой символ вне диапазона символов ASCII будет просто уничтожен до случайного представления, в зависимости от текущего состояния исполняемых потоков.

Работоспособное решение:

      #include <cvt/wstring>
#include <stringapiset.h>

Platform::String^ testText = "foo";
const wchar_t* pWStr = testText->Data();
int bufferSize = WideCharToMultiByte(CP_UTF8, 0, pWStr, -1, NULL, 0, NULL, NULL);
char* stringUtf8 = new char[bufferSize + 1];
memset(stringUtf8, 0, bufferSize + 1);
if (0 == WideCharToMultiByte(CP_UTF8, 0, pWStr, -1, stringUtf8, bufferSize, NULL, NULL))
{
    throw std::exception("Can't convert string to Unicode");
}
const char* rawCstring = std::string(stringUtf8).c_str();
delete[] stringUtf8;
Другие вопросы по тегам