Как конвертировать 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;