WideCharToMultiByte msvc 2012 bug?

Здравствуйте.

Есть некая ф-я конвертации wchar_t* строки:
bool WcharToString(const wchar_t* wstr, std::string& converted, UINT codePage = CP_ACP)
{
	if(wstr)
	{
		int length = ::WideCharToMultiByte(codePage, 0, wstr, -1, NULL, 0, NULL, NULL);
		char* str = new char[length + 1];
		str[length] = '\0';
		
		// ignoring returned value
		::WideCharToMultiByte(codePage, 0, wstr, -1, str, length, NULL, NULL);
		converted.assign(str);
		delete [] str;
		return true;
	}
	return false;
}



И она, оказывается, прекрасно работает, если использовать 2010 студию, но не работает, если это 2012 студия. Что скажете по этому поводу — некорректно написана ф-я выше или баг библиотек 2012 студии?

( сама WideCharToMultiByte обьявляется в WinNls.h 2010 студии и в Stringapiset.h 2012 — т.е. что то меняли :) ).

Если баг, то может сообщить Microsoft? А если не баг, подскажите как сделать правильно.


Заранее спасибо.
  • Вопрос задан
  • 4365 просмотров
Решения вопроса 1
::WideCharToMultiByte(codePage, 0, wstr, -1, str, length, NULL, NULL);
Небольшая поправка: размер целевого буфера должен быть не length, а length+1 (ведь именно столько памяти выделено), тогда не придётся вставлять завершающий ноль вручную, функция сделает это сама.

Что касается проблемы, я не понял, при чём тут UTF-8. Конвертируется-то не в UTF-8 (CP_UTF8), а в ANSI (CP_ACP). И в отладчике Студии отображается ANSI. Только в 2012 этот ANSI из другой кодовой страницы. То есть, судя по всему, имеет место баг отладчика Студии. Если раскрыть строку и рассмотреть её посимвольно, то будет видно, что коды символов в обоих случаях одинаковые. Просто 2010 для отображения этих кодов в виде строки использует одну кодовую страницу (русскую, 1251), а 2012 — другую (1252, западную).
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@vScherba
А попробуйте явно указать кодировку вместо CP_ACP.

Часто для перекодировки используется прием:
string str = _bstr_t(wstr).operator char*();

.operator char*() в реализации использует WideCharToMultiByte. Если этот прием также сработает неправильно, скорее всего баг у Майкрософт.
Ответ написан
ixSci
@ixSci
Если Вы используете 2012 студию, то почему бы не писать:
std::string utilities::utf16ToUtf8(const std::wstring& utf16) { std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> convert; return convert.to_bytes(utf16.c_str()); }
Ответ написан
kostik450
@kostik450
У меня тоже были кракозябры вместо русских букв, решилось так:

#include <locale.h>
int main (int argc, char **argv)
{
   setlocale (LC_ALL, ".1251");
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы