Как я могу использовать wstring(s) в API Linux?

Я хочу разработать приложение в Linux. Я хочу использовать wstring, потому что мое приложение должно поддерживать Unicode, и я не хочу использовать строки UTF-8.

В ОС Windows использовать wstring очень просто. потому что любой ANSI API имеет форму юникода. например, есть два API CreateProcess, первый API — CreateProcessA, а второй API — CreateProcessW.

wstring app = L"C:\\test.exe";
CreateProcess
(
  app.c_str(), // EASY!
  ....
);

Но кажется, работать с wstring в Linux сложно! например, в Linux есть API под названием parport_open (Это просто пример).

и я не знаю, как отправить мою wstring в этот API (или API, такие как parport_open, которые принимают строковый параметр).

wstring name = L"myname";
parport_open
(
  0, // or a valid number. It is not important in this question.
  name.c_str(), // Error: because type of this parameter is char* not wchat_t*
  ....
);

Мой вопрос: как я могу использовать wstring(s) в API Linux?

Примечание. Я не хочу использовать строки UTF-8.

Спасибо


person Amir Saniyan    schedule 04.09.2011    source источник
comment
Ваш первоначальный пример неверен, CreateProcess() нельзя вызывать с wchar_t*, а только с _tchar*. Кроме того, широкие символы не имеют непосредственного отношения к Unicode, и, кроме того, широкие символы Windows являются преступлением против человечества. Возможно, эта моя тирада немного объясняет широкие символы и что с ними делать.   -  person Kerrek SB    schedule 04.09.2011
comment
На самом деле функции CreateProcess не существует, это макрос для CreateProcessW/CreateProcessA в зависимости от настроек макроса _UNICODE.   -  person Matteo Italia    schedule 04.09.2011
comment
Нуб Unicode здесь: не будет ли самым простым способом взломать рабочую версию вместе сделать вспомогательную функцию, которая использует wcstombs и возвращает std::string со следующим использованием parport_open(0, toutf8(name).c_str(), ....);?   -  person user786653    schedule 04.09.2011
comment
@ user786653: и вы будете выполнять такое преобразование (которое, кстати, нужно каждый раз выделять память) для каждого системного вызова только потому, что вы не хотите использовать UTF-8?   -  person Matteo Italia    schedule 04.09.2011
comment
@Kerrek Широкие символы Windows - преступление против человечества? Ну, может быть, но вы предлагаете не использовать их при кодировании в Windows? А как бы вы реализовали текст в Windows NT?   -  person David Heffernan    schedule 04.09.2011
comment
@David: Я не говорю, что Windows NT не замешана в преступлении :-) Я понимаю исторические причины этого, но в конечном итоге это привело к распространению очень неприятной идиомы, которая доставляет много головной боли. Я ссылаюсь на свой связанный пост: используйте Unicode внутри и конвертируйте в широкострочную или многобайтовую строку в четко определенных интерфейсах по мере необходимости, что должно сделать ваш код относительно чистым, удобным для обслуживания и переносимым.   -  person Kerrek SB    schedule 04.09.2011
comment
@Kerrek: разве это не то, что обычно делается - использование внутри UTF-8/16 (тот, который больше всего нравится вашей платформе), а затем преобразование в определенную кодировку, когда это необходимо?   -  person Matteo Italia    schedule 04.09.2011
comment
@Matteo: Я бы так не сказал: я бы либо использовал UTF32 внутри, если мне нужно знать кодировку, либо wchar_t, если я этого не знаю. Я бы использовал только UTF-8 для взаимодействия со средой, а UTF16 (с явным именем) никогда. (И я бы взаимодействовал с API Windows через wchars без кодирования.)   -  person Kerrek SB    schedule 04.09.2011
comment
См. Почему UTF-8 используется с Unix/Linux.   -  person Jonathan Leffler    schedule 04.09.2011


Ответы (2)


API-интерфейсы Linux (на последних ядрах и с правильными настройками локали) почти во всех дистрибутивах по умолчанию используют строки UTF-81. Вы тоже должны использовать их внутри своего кода. Сопротивление бесполезно.

wchar_t (и, следовательно, wstring) в Windows были удобны только тогда, когда Unicode был ограничен 65536 символами (т.е. wchar_t использовались для UCS-2), теперь, когда 16-битная Windows wchar_t используется для UTF-16, преимущество 1 wchar_t= 1 символ Unicode давно исчез, поэтому у вас те же недостатки, что и при использовании UTF-8. На сегодняшний день ИМХО линуксовый подход самый правильный. (Еще один мой ответ на UTF-16 и почему Windows и Java используют его )

Между прочим, и string, и wstring не поддерживают кодировку, поэтому вы не можете надежно использовать ни одну из этих двух для управления кодовыми точками Unicode. Я слышал, что wxString из инструментария wxWidgets хорошо обрабатывает UTF-8, но я никогда не проводил обширных исследований по этому поводу.


  1. на самом деле, как указано ниже, ядро ​​стремится быть независимым от кодировки, т. е. оно обрабатывает строки как непрозрачные последовательности (оканчивающихся NUL?) байтов (и поэтому кодировки, использующие «более крупные» типы символов, такие как UTF-16, не могут быть использовал). С другой стороны, везде, где выполняются фактические манипуляции со строками, используется текущая настройка локали, и по умолчанию почти в любом современном дистрибутиве Linux она установлена ​​​​на UTF-8 (что для меня является разумным значением по умолчанию).
person Matteo Italia    schedule 04.09.2011
comment
Спорить о том, лучше ли UTF-8, чем UTF-16, несколько спорно (UTF-8 лучше). В конечном счете, все, что имеет значение, это то, что Windows использует UTF-16, а Linux использует UTF-8, а остальные должны последовать их примеру. - person David Heffernan; 04.09.2011
comment
Если требуется явный Unicode, а не набор символов моей платформы, вам вообще не следует использовать широкие символы, а вместо этого переключиться на современный компилятор и использовать char32_t. - person Kerrek SB; 04.09.2011
comment
Дэвид: На самом деле, где Linux использует UTF-8? Файловые системы, как одно из наиболее важных приложений, вообще не определяют никаких кодировок, они просто используют байтовые строки с завершающим нулем. Я думаю, что только NTFS по какой-то причине использует 16-битные строки с завершающим нулем (но также без семантики кодирования!). - person Kerrek SB; 04.09.2011
comment
@David: я хочу сказать, что, на мой взгляд, если бы Windows пришлось переписывать сегодня, возможно, было бы разумнее просто использовать UTF-8 и забыть о UTF-16 и W/A. Но я с вами в том, что спорить о вещах, которые нельзя изменить, бесполезно. - person Matteo Italia; 04.09.2011
comment
@Kerrek: AFAIK kernel Linux пытается быть независимым от кодирования файловых систем. Там, где важна кодировка, следует использовать текущую настройку локали, и в настоящее время почти везде по умолчанию используется UTF-8. - person Matteo Italia; 04.09.2011
comment
@Matteo: Существуют ли какие-либо функции Linux API, требующие знания кодировок? Что у тебя было на уме? - person Kerrek SB; 04.09.2011
comment
@Matteo Да, если бы Windows была переписана, это было бы сделано с кодировками char * и UTF8. Чего многие люди не понимают, так это того, что Windows поддерживала Unicode до появления UTF-8! - person David Heffernan; 04.09.2011
comment
@David: я знаю, и я действительно написал ответ об этом. :) Дело в том, что, когда эти решения были приняты в проекте NT (начало девяностых или даже раньше?), Unicode был ограничен BMP, поэтому было разумным решением просто использовать 2-байтовые wchar_ts, которые имели преимущество 1 wchar_t=1 символ Unicode - и UTF-8 родился в 1992 году, чтобы удовлетворить потребности UNIces. IIRC расширение до 2 ^ 32 символов было стандартизировано примерно в 1994-1995 годах (NT4, Windows 95), поэтому у Microsoft никогда не было возможности сделать что-то по-другому. - person Matteo Italia; 04.09.2011
comment
@Matteo: Nitpick: в настоящее время в Unicode есть место для 2 ^ 21 символа. UTF-8 может представлять до 2^36 значений. - person Kerrek SB; 04.09.2011
comment
@Kerrek Вместо того, чтобы придираться и злиться на широкомасштабные преступления против человечества и чертовски сбивать с толку бедного задающего вопрос, как насчет практического совета? - person David Heffernan; 04.09.2011
comment
@Kerrek: только что проверил, ты прав, на самом деле используется только 17 самолетов. - person Matteo Italia; 04.09.2011
comment
@David: Совет содержится в моем посте, на который я дал ссылку :-) Из-за огромного количества путаницы, связанной с кодировками и широкими символами, я думаю, что немного придираться к безопасности... - person Kerrek SB; 04.09.2011
comment
@Jonathan: Вы правы, я должен был сказать, что схема Томпсона может использоваться до 36 бит, но для 21 бита требуется не более 4 кодовых единиц. Спасибо! - person Kerrek SB; 04.09.2011

Я не хочу использовать строки UTF-8.

Что ж, вам нужно будет преодолеть это нежелание, по крайней мере, при вызове API. Linux использует кодировку однобайтовых строк, неизменно UTF-8. Очевидно, что вы должны использовать тип однобайтовой строки, так как вы, очевидно, не можете передавать расширенные символы функции, которая ожидает char*. Используйте string вместо wstring.

person David Heffernan    schedule 04.09.2011
comment
Я не совсем уверен, что вы подразумеваете под Linux, использующим UTF-8, и имеет ли это на самом деле смысл... - person Kerrek SB; 04.09.2011