Qt, MSVC и /Zc: wchar_t- == Я хочу взорвать мир
Итак, Qt скомпилирован с /Zc: wchar_t- на окнах. Это означает, что вместо wchar_t является typedef для некоторого внутреннего типа (__wchar_t, я думаю), он становится typedef для unsigned short
. Самое замечательное в этом заключается в том, что значение по умолчанию для MSVC - это противоположное, что, конечно же, означает, что используемые библиотеки, скорее всего, скомпилированы с wchar_t
другим типом, чем Qt wchar_t
.
Это не станет проблемой, пока вы не попытаетесь использовать что-то вроде std::wstring
в своем коде; особенно когда одна или несколько библиотек имеют функции, которые принимают ее как параметры. Эффективно получается, что ваш код с удовольствием компилируется, но затем не связывается, потому что ищет определения с помощью std::wstring<unsigned short...>
, но они содержат только определения, ожидающие std::wstring<__wchar_t...>
(или что-то еще).
Итак, я сделал несколько поисков в Интернете и наткнулся на эту ссылку: https://bugreports.qt.io/browse/QTBUG-6345
Основываясь на заявлении Thiago Macieira, "Извините, мы не будем поддерживать построение Qt, как это", я был обеспокоен тем, что исправление Qt для работы, как и все остальное, может вызвать некоторые проблемы и пытаться избежать этого. Мы перекомпилировали все наши библиотеки поддержки с флагом /Zc: wchar_t- и были достаточно довольны этим до тех пор, пока пару дней назад, когда мы начали пытаться выполнить перенос (мы переходим от Wx к Qt), некоторые сериализации код.
Из-за того, как работает win32, и поскольку Wx просто обертывает win32, мы использовали std::wstring
для представления строковых данных с намерением сделать наш продукт максимально готовым. Мы провели некоторое тестирование, и Wx не работал с многобайтными символами при попытке распечатать специальные материалы (даже не такие специальные вещи, как символ степени, был проблемой). Я не уверен, что у Qt есть эта проблема, поскольку QString - это не просто оболочка для базового типа _TCHAR, а монстра Unicode.
Во всяком случае, библиотека сериализации в boost скомпилировала части. Мы попытались перекомпилировать boost с помощью /Zc: wchar_t-, но до сих пор наши попытки сказать bjam сделать это остались без внимания. Мы в тупике.
Откуда я сижу, у меня есть три варианта:
-
Перекомпилируйте Qt и надейтесь, что он работает с /Zc: wchar_t. Там есть некоторые доказательства в Интернете, которые другие сделали это, но я не могу предсказать, что произойдет. Все попытки спросить Qt людей на форумах и т.д. Остались без ответа. Черт, даже в этом очень сообщении об ошибке кто-то спрашивает, почему, и он просто сидел там год.
-
Продолжайте сражаться с bjam, пока он не слушает. Прямо сейчас у меня есть кто-то, кто делает это, и у меня больше опыта борьбы с вещами, чтобы получить то, что я хочу, но я вынужден признать, что устал от этого. Я также обеспокоен тем, что я буду использовать эту проблему только потому, что Qt хочет быть c ** t.
-
Прекратите использование wchar_t для чего-либо. К сожалению, мой опыт i18n в значительной степени равен 0, но мне кажется, что мне просто нужно найти право на/из функции в QString (он имеет BUNCH) для кодирования Unicode в 8-байтный и наоборот. Функции UTF8 выглядят многообещающими, но я действительно хочу быть уверенным, что никакие данные не будут потеряны, если кто-то из Zimbabfuckegypt начнет писать на своем родном языке, а документация в QString немного пугает меня мыслью о том, что это может произойти. Конечно, я всегда мог столкнуться с какой-то библиотекой, которая настаивает на том, что я использую wchar_t, а затем возвращаюсь к 1 или 2, но я скорее сомневаюсь, что это произойдет.
Итак, что мой вопрос...
Какой из этих вариантов - мой лучший выбор? Может ли Qt в конечном итоге заставить меня вытолкнуть мои собственные глаза, потому что я решил скомпилировать его с помощью /Zc: wchar_t?
Какое магическое заклинание должно быть усилено для создания с помощью /Zc: wchar_t- и будет ли это причинять постоянный умственный ущерб?
Могу ли я обойтись просто с использованием стандартных 8-битных (ну, "обычных" ) классов символов и быть совместимым/готовым i18n?
Как другие разработчики Qt справляются с этим беспорядком?
Ответы
Ответ 1
Я согласен с замечанием Öö Tiib
Этот вариант, возможно, для совместимость с каким-то старым наследием pre-wchar_t.
Имея в виду, что Qt переносится на многие разные платформы (включая встроенные системы), некоторые из них не имеют достойного компилятора С++, я бы предположил, что этот коммутатор просто позволяет компилировать Qt на этих платформах. Я имею в виду, что это, вероятно, не то, что Qt полагается на правильную работу. Если бы это было так, это означало бы, что дизайн Qt глубоко нарушен, на мой взгляд. Поэтому вариант 1 должен работать.
Сказав, что я определенно рекомендую выбрать вариант 3, потому что
-
wchar_t
дает вам почти ничего
отношение к i18n
- поскольку вы заметили, что Qt имеет очень способный класс строк
что делает задачу легкой (см.
Интернационализация с Qt)
Вы можете взглянуть на результаты поиска wchar_t
на [email protected], задайте свой вопрос там и поговорите с Тьяго Масиейрой на freenode.net #qt irc, где Тьяго очень активен.
Ответ 2
Наткнулся на ту же проблему...
Очевидно, что bjam ожидает cxxflags=-Zcwchar_t-
После создания статических сериализационных библиотек через
bjam --with-serialization toolset=msvc-8.0 variant=debug threading=multi link=static cxxflags=-Zc:wchar_t-
все связано как ожидалось.
Надеюсь, это поможет кому угодно.
Ответ 3
wchar_t должен быть типом типа bool или long. Для его определения не требуются заголовки.
Вы использовали этот параметр "wchar_t is undefined type". Затем вы вводите typedef wchar_t как unsigned short, а затем задаетесь вопросом, что больше ничего не работает?
Этот вариант, возможно, совместим с каким-то старым предыдущим кодом pre-wchar_t. Просто... никогда не используйте его. В противном случае ни на что С++ не ссылается на него, потому что функции, которые принимают параметры wchar_t, по-разному управляются именами, чем функции, которые принимают неподписанные короткие параметры.
Если какая-либо библиотека скомпилирована с некоторыми странными параметрами, то создайте ее с правильными параметрами. Когда необходимо, исправьте его код. Если вы не можете этого сделать, вы не должны использовать эту библиотеку. Каждая строка кода в вашем проекте на С++ поддерживается вами.
Ответ 4
Поместите это здесь как ответ, потому что он слишком длинный для комментариев.
Вот один из ответов на вопрос о том, почему LNK2019 может быть заменен как "символ не найден" (источник):
- Вы смешиваете код, который использует собственный wchar_t с кодом, который этого не делает. Работа по совместимости языка С++, которая была выполнена в Visual С++ 2005, сделана
По умолчанию используется wchar_t собственный тип. Вы должны использовать /Zc: wchar_t-
компилятор для генерации кода, совместимого с модулями, скомпилированными с помощью используя более ранние версии Visual С++. Если не все модули были скомпилированные с использованием тех же настроек /Zc: wchar_t, типы ссылок могут быть указаны не разрешать совместимые типы. Убедитесь, что типы wchar_t во всех
модули совместимы либо путем обновления типов, которые используются,
или с помощью параметров согласованного /Zc: wchar_t при компиляции.
Таким образом, это может быть основной причиной того, почему /Zc: wchar_t- присутствует во всех файлах mkspec, связанных с cl.exe, а также почему вы, вероятно, не нуждаетесь в нем.
Мне нравится иметь native wchar_t
, потому что он иногда легко конвертировать между строками, которые ожидаются windows api, и QString.