Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Visual C++ / MFC / WTL > О поддержке приложением Unicode


Автор: Black_Dragon 03.04.20, 08:30
Из того, что нагуглилось по Unicode, это просто стандарт кодирования символов (сильно в вопрос не погружался).

Есть проекты в Visual Studio 2019 (MFC-шные)
В настройках проекта есть настройка набора символов: типа ничего, юникод и многобайтовая.

Есть приложение.
1) Считывает данные по сети SNMP в char[]
2) Считывает данные ОС NetAPI (тоже сетевую информацию) в WCHAR[] (режим FORCE_UNICODE)
3) Работает с MySQL через std::string
4) и для отладки вспомогательное GUI (приложение работает как служба) работает со CString

В приложении используется std::wstring
1) конвертируется string->wstring
3) для работы с базой (API) используется string, при работе конвертируем string<->wstring

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    using CStr = std::string;
    using CWideStr = std::wstring;
    // convert UTF-8 string to wstring
    CWideStr utf8_to_wstring(const CStr &str)
    {
        std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;
        return myconv.from_bytes(str);
    }
     
    // convert wstring to UTF-8 string
    CStr wstring_to_utf8(const CWideStr &str)
    {
        std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;
        return myconv.to_bytes(str);
    }


Смотрю на весь код, и как-то ощущается, что wstring то мне и не нужен.

Если в настройках проекта отключить юникод, то для CString будет использоваться char, т.е., как я понимаю, для MFC классов поменяется char/wchar_t.
Так вот, без выключений этой опции (оставить юникод), могу спокойно отказаться от wstring, конвертировать только для отображения информации (но без юникода и конвертировать не придется), ну и NetAPI тогда конвертировать в string (что и так происходит при записи в субд).
Но как-то глобально скажется, отключение юникода в настройках проекта? Может там другие библиотеки будут использоваться, у которых нет поддержки юникода или что-то еще... (используются языки английский, русский и казахский)

+
В другом приложении работаю с MS SQL, который, как я понимаю, работает с WCHAR
#include <sqlext.h>
#include <sqltypes.h>
#include <sql.h>

Автор: jcxz 22.06.20, 08:39
А зачем отказываться от Unicode? Тем более если нужны 3 разных языка (не знаю - казахский алфавит влезает в старшую половину 128...255?)
Можно конечно поставить в настройке набора символов: NONE и везде будут использоваться char-варианты библиотечных функций. А при необходимости Unicode: явно использовать wchar_t и варианты функций с явным указанием Unicode-библиотеки - типа SendMessageW().
Но вот у меня сейчас есть большой проект, где изначально я так и сделал (все строки - char), а теперь хотелось бы переделать под Unicode (потребовались разные языки), но уже перелопатить весь проект - это нужно подвиг совершить, слишком трудозатратно. :(

Автор: Black_Dragon 22.06.20, 09:01
По размеру должен, алфавит 42...
Но у меня есть VBScript, с русскими и казахским текстом, при файле UTF-8 не работает, заработало только при UTF-16. Так что....

Вопрос в том, как и на что влияет эта настройка.

Автор: jcxz 22.06.20, 09:16
Цитата Black_Dragon @
Вопрос в том, как и на что влияет эта настройка.

В первую очередь повлияет на используемую библиотеку функций. При "NONE" на место SendMessage() будет подставлена SendMessageA(), а при "UNICODE" - SendMessageW().
Но также можно и явно указывать требуемый вариант функции. Если нужно.
Например - в моём приложении скомпилённом в "NONE", есть пара мест где я устанавливаю Unicode-надписи для контролов через SendMessageW(). Всё работает ок.

Автор: Black_Dragon 22.06.20, 11:53
Цитата jcxz @
В первую очередь повлияет на используемую библиотеку функций. При "NONE" на место SendMessage() будет подставлена SendMessageA(), а при "UNICODE" - SendMessageW().

Это просто выбор макроса в инклудах для удобства, я про них знаю...
Есть ли какие-то существенные изменения в тех же либах или где-то еще (подводные камни), или это только для удобство?

Автор: Wound 22.06.20, 14:12
Цитата Black_Dragon @
Но как-то глобально скажется, отключение юникода в настройках проекта? Может там другие библиотеки будут использоваться, у которых нет поддержки юникода или что-то еще... (используются языки английский, русский и казахский)

Будут вызываться функции принимающие юникод строки(с префиксом W) - если включен юникод, и будут вызываться функции принимающие ASCII строку, если ты выключишь юникод, допустим, в коде вызывается у тебя там функция: GetComputerName
Если включен Unicode, то вызовется эта версия:
https://docs.microsoft.com/ru-ru/windows/wi...etcomputernamew
Если включен ansi, то вызовется эта версия:
https://docs.microsoft.com/ru-ru/windows/wi...etcomputernamea

Разница в принимающих аргументах. Так же всякие классы обертки типа CString будут использовать CHAR вместо WCHAR(для юникодной конфигурации).

Если ты везде юзал MFCШные универсальные типы, аля там TCHAR, LPCTSTR, CString и т.д., вместо например char, std::string/std::wstring, то проблем быть не должно, при смене настройки, просто будут типы данных ansi использоваться, размер типа станет 8 бит(для юникода 16 бит). Ну и не будут отображаться русские/казахские/еще какие то символы, хотя через локаль настроить можно.
Ну и если вдруг что то случится, скорее всего будет ошибка компиляции, т.к. типа данных изменится, и если ты где то передавал явную юникод строку в функцию например GetComputerName(или подобной), то после смены текущей настройки будет вызвана функция с префиксом А, которая требует ascii строку, а не wchar_t, соответственно сразу увидишь эти места.

Автор: ЫукпШ 22.06.20, 16:13
Цитата Black_Dragon @
Есть ли какие-то существенные изменения в тех же либах...

Рихтер
страница 13.

Автор: JoeUser 22.06.20, 16:23
Скрытый текст
ЫукпШ, злой ты человек! :( Я понимаю бы - Рихреру в карман. Так ты поощряешь этих кривых калдырей-плагиаторов.
Будь мужиком - начни давать ссылки на электронные версии полезного оригинального материала!
>:(
Это шутка, есличо! :lol:

Автор: Black_Dragon 24.06.20, 04:15
Цитата Wound @
(с префиксом W)

Про это я знаю.
Это макросы для удобства.

В программе текст храниться в std::wstring.
Данные с сети считываются:
1) std::string (конвертация в std::wstring)
2) std::wstring
Данные считываются и записываются в СУБД MySQL (UTF-8)
3) std::string (конвертация в std::wstring и обратно)
Ну и для версии программы с GUI
4) CString для вывода в таблицу и т.п.

Если опустить п.4, то кажется оптимальнее использовать std::string, а если вообще отключить уникод, то CString будет char, будут ли проблемы с выводом unicode...

Так же при работе с MS SQL можно так же char/wchar юзать, uncode (utf-8) будет работать в случае char?

Вообщем цель, сидеть на 8-битах с русским/казахским текстом возможна ли?

Автор: Wound 24.06.20, 07:19
Цитата Black_Dragon @
Вообщем цель, сидеть на 8-битах с русским/казахским текстом возможна ли?

Наверное, не пробовал. Попробуй добавить второй язык в систему и написать hellow world в котором в консоль вывести казахский текст, только перед этим выстави казахскую локаль.

Автор: Mr.Delphist 06.07.20, 12:51
Если сидеть на 8 битах, то неизбежно возникает необходимость явно задавать кодовую страницу. Что немножечко неудобно, в свете современных тенденций разработки. Тот же UTF-8 позволяет сформировать строку из русских букв, казахских, туда же пришить немецкие умляуты и китайские иероглифы. В одной и той же строке.

Возможно, это из-за недопонимания, что UTF-8 - это не строка в привычном понимании языков программирования, а скорее байтовый формат буфера? И если мы вводим понятие у себя кодовой страницы для восьмибитной строки, то по сути переизобретаем UTF-8 из желудей и спичек.

Автор: ЫукпШ 06.07.20, 13:50
Цитата Mr.Delphist @
Тот же UTF-8 позволяет сформировать строку из русских букв, казахских, туда же пришить немецкие умляуты и китайские иероглифы. В одной и той же строке.

Насколько я понимаю, сделано так:
UTF-8 - это одна из нескольких кодировок Юникода.
Широко используется в Linux/Unix системах, в том числе
для вывода в консоль.
У Виндуса используется Юникод - кодировка в формате UTF-16.
Но для совместимости со старыми приложениями DOS в консоли
используется кодировка OEM. Т.е.старая, байтовая, со всеми
её недостатками.
Виндус своими встроенными средствами может делать любые преобразования
ASCII-UTF8-UTF16-OEM. Так что с преобразованиями проблем не будет,
но приложение лучше делать Unicode (UTF-16).
Это повышает быстродействие, потому что любая ASCII - функция системы
использует дополнительное преобразование ASCII<->Unicode и последующий
вызов Unicode - функции.
---
Иллюзия думать, что "сейчас я запишу в Unicode-строку" русские, арабские и японские символы
и увижу всё это на экране.
Скорее всего, на экране будут кракозябры.
Поскольку Unicode - это необходимое условие, но не достаточное.
Нужно чтобы используемый фонт имел в своём составе отображение всех этих символов.
Но разработчик фонта не знает заранее, какие символы мне понадобятся.
Значит, надо производить поддержку всех символов, изобретённых Человечеством,
а это действительно технически сложно.
---
Разговор про казахский язык вообще не понятен.
Отображаются не языки, отображаются алфавиты.
До некоторого времени, Казахстан использовал кириллицу.
Не так давно, руководство Казахстана объявило, что переходит на латиницу.
В любом случае, используемые символы алфавитов предназначены
для воспроизведения слов на казахском языке - но своего
казахского алфавита ведь нет ?.
Если это так, можно предположить, что русская OEM (CP-866) - кодировка подходит для казахского
языка. Та самая, что у русского Виндуса установлена для консоли по умолчанию.

Автор: JoeUser 06.07.20, 15:02
ЫукпШ, чуть малеха ошибаешься. Все дело в терминологии ... Просто нужно еще раз обратиться к английской аббревиатуре используемых терминов.

UNICODE - представляет собой стандарт кодирования символов, и определяет набор символов, а если точнее - глифов (т.е. символов с их начертанием и принадлежности языковой плоскости). Последняя версия юникода 13.0 (март 2020) определяет 143 859 символов, что эквивалентно ) hex - 0002 31F3

UTF (UTF-8,UTF-16,UTF-32) - В вики написана отчасти муть, т.к. названия плавают от "кодировки" до "представления". Лучше ориентироваться на оригинальное название Unicode Transformation Format. Акцент - на втором слове.

UTF-8 - формат представления символов Юникода, с переменным числом байт (от 1 до 4)
UTF-16 - формат представления символов Юникода, с переменным числом байт (2 или 4)
UTF-32 - формат представления символов Юникода, с постоянным числом байт 4

Характеристики

UTF-8 - лучшая компактность в памяти, самый медленный парсинг буфера в глифы
UTF-16 - средняя компактность в памяти, средний-быстрый по скорости парсинг буфера в глифы
UTF-32 - худшая компактность в памяти, самый быстрый по скорости парсинг буфера в глифы

Что касается венды - своем API она пользует UTF-16 (а если точнее - UTF-16LE). Таким образом,
если при проектировании ориентироваться на UTF-8, то наиболее частыми преобразованиями,
при использовании API Windows, будут двусторонние операции UTF8<-->UTF-16LE. А вот одно-
битные ASCII варианты из API Windows - это уже анохронизм.

Добавлено
Цитата ЫукпШ @
Иллюзия думать, что "сейчас я запишу в Unicode-строку" русские, арабские и японские символы
и увижу всё это на экране. Скорее всего, на экране будут кракозябры.


Это - перпендикулярный вопрос :lol: Тут уже идет речь не о кодировках и/или форматах,
а о полноте наборов (плоскостей) в конкретном Unicode-шрифте. Если мне память не изменяет, то самые
полные наборы глифов - содержат шрифты семейства Note.

Вики:

Цитата
Хотя формы записи UTF-8 и UTF-32 позволяют кодировать до 231 (2 147 483 648) кодовых позиций, было принято решение использовать лишь 1 112 064 для совместимости с UTF-16. Впрочем, даже и этого в данный момент более чем достаточно — в версии 13.0 используется всего 143 859 кодовых позиций.

Кодовое пространство разбито на 17 плоскостей (англ. planes) по 216 (65 536) символов. Нулевая плоскость (plane 0) называется базовой (basic) и содержит символы наиболее употребительных письменностей. Остальные плоскости — дополнительные (supplementary). Первая плоскость (plane 1) используется в основном для исторических письменностей, вторая (plane 2) — для редко используемых иероглифов китайского письма (ККЯ), третья (plane 3) зарезервирована для архаичных китайских иероглифов[66]. Плоскость 14 отведена для символов, используемых по особому назначению. Плоскости 15 и 16 выделены для частного употребления[7].

Автор: ЫукпШ 06.07.20, 15:11
Цитата JoeUser @
Что касается венды - своем API она пользует UTF-16 (а если точнее - UTF-16LE). Таким образом,
если при проектировании ориентироваться на UTF-8, то наиболее частыми преобразованиями,
при использовании API Windows, будут двусторонние операции UTF8<-->UTF-16LE. А вот одно-
битные ASCII варианты из API Windows - это уже анохронизм.

Нет. Виндус не производит поддержку приложений UTF-8.
Либо ASCII, либо UTF-16.
Преобразование в UTF-8 полезно при обмене с linux-системами
или при обработке linux-файлов.

Автор: JoeUser 06.07.20, 15:14
Цитата ЫукпШ @
Нет. Виндус не производит поддержку приложений UTF-8.

Нет - зеленое! :lool: Где я говорил о поддержке UTF-8 виндой?
Я сказал:
Цитата ЫукпШ @
если при проектировании ориентироваться на UTF-8

Имеется ввиду твоей создаваемой программы.

Добавлено
Цитата ЫукпШ @
Преобразование в UTF-8

А хранение любых данных, для который некритична скорость парсинга (названия элементов управления UI, текстовое описание ошибок, сообщений & etc...) - лучше в UTF-8 из практических соображений.

Автор: ЫукпШ 06.07.20, 15:37
Цитата JoeUser @
Что касается венды - своем API она пользует UTF-16 (а если точнее - UTF-16LE). Таким образом,
если при проектировании ориентироваться на UTF-8, то наиболее частыми преобразованиями,
при использовании API Windows, будут двусторонние операции UTF8<-->UTF-16LE. А вот одно-
битные ASCII варианты из API Windows - это уже анохронизм.

Ты , что-ли, болен ? Это кто написал ?
Как же я могу "ориентироваться на UTF-8" если
ни сама Виндус, ни средства разработки UTF-8 не используют ?

Автор: JoeUser 06.07.20, 15:52
Цитата ЫукпШ @
Ты , что-ли, болен ?

Ага. Болен. Дитер Болен :lol:

Цитата ЫукпШ @
Как же я могу "ориентироваться на UTF-8" если
ни сама Виндус, ни средства разработки UTF-8 не используют ?

Врешь и не краснеешь!

Добавлено
Цитата ЫукпШ @
Это кто написал ?

А это кто-то читал как написано, а не как захотелось прочесть?

Автор: JoeUser 06.07.20, 19:41
Цитата ЫукпШ @
ни сама Виндус

И в догоночку ... а это что, а это что, не город?!! (С) :lol:

Автор: Mr.Delphist 07.07.20, 18:34
Цитата ЫукпШ @
Иллюзия думать, что "сейчас я запишу в Unicode-строку" русские, арабские и японские символы
и увижу всё это на экране.
Скорее всего, на экране будут кракозябры.
Поскольку Unicode - это необходимое условие, но не достаточное.
Нужно чтобы используемый фонт имел в своём составе отображение всех этих символов.
Но разработчик фонта не знает заранее, какие символы мне понадобятся.
Значит, надо производить поддержку всех символов, изобретённых Человечеством,
а это действительно технически сложно.


Согласен, описание в шрифте должно быть. Если нет - будет дефолтный символ (обычно квадратик). Решается установкой language pack - как минимум системные шрифты будут с нужной отрисовкой.


Цитата ЫукпШ @
Разговор про казахский язык вообще не понятен.
Отображаются не языки, отображаются алфавиты.
До некоторого времени, Казахстан использовал кириллицу.
Не так давно, руководство Казахстана объявило, что переходит на латиницу.
В любом случае, используемые символы алфавитов предназначены
для воспроизведения слов на казахском языке - но своего
казахского алфавита ведь нет ?.


А горловые звуки? У них свой глиф, пусть и на основе стандартной буквы. В новой версии латиницы вроде отказались от спец-глифов в пользу двубуквенных дифтонгов на британский манер, но дореволюционная их латиница как минимум тоже была с спец-глифами на основе родственной буквы.

Добавлено
Цитата ЫукпШ @
Если это так, можно предположить, что русская OEM (CP-866) - кодировка подходит для казахского
языка. Та самая, что у русского Виндуса установлена для консоли по умолчанию.


Не поленился, поискал - страницы №920 для MS DOS и №1048 для Windows.

Автор: jcxz 07.07.20, 20:16
Цитата ЫукпШ @
Если это так, можно предположить, что русская OEM (CP-866) - кодировка подходит для казахского
Это навряд-ли. Насколько помню (из своего казахского периода жизни) в казахской азбуке более 50 буковок. Там одних 'К' несколько штук в разных вариациях. :scratch:

Автор: Black_Dragon 08.07.20, 05:53
Цитата jcxz @
в казахской азбуке более 50 буковок

42
Цитата jcxz @
Там одних 'К' несколько штук в разных вариациях

2


Тут вся сложность (неудобство) в том, что надо оперировать одновременно разным форматом хранения/передачи.
MySQL (UTF-8) - std::string (char)
GUI - CString (wchar).
Поучение информации: числа (важно), wchar[] (важно, на русском), char[] (не важное и пока только на английском)

Внутреннее хранение std::wstring.
Когда программа перейдет в разряд Служба, то GUI отпадет...

Автор: Gonarh 08.07.20, 05:55
Цитата jcxz @
в казахской азбуке более 50 буковок.

Зачем врать, всего 42.
Цитата
Там одних 'К' несколько штук в разных вариациях. :scratch:

Ойли. Всего два начертания. Первое как в кириллице, второе с хвостиком - Қ.

Добавлено
Второйнах :lol:

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)