So Qt is compiled with /Zc:wchar_t- on windows. What this means is that instead of wchar_t being a typedef for some internal type (__wchar_t I think) it becomes a typedef for unsigned short
. The really cool thing about this is that the default for MSVC is the opposite, which of course means that the libraries you're using are likely compiled with wchar_t
being a different type than Qt's wchar_t
.
This doesn't become an issue of course until you try to use something like std::wstring
in your code; especially when one or more libraries have functions that accept it as parameters. What effectively happens is that your code happily compiles but then fails to link because it's looking for definitions using std::wstring<unsigned short...>
but they only contain definitions expecting std::wstring<__wchar_t...>
(or whatever).
So I did some web searching and ran into this link: https://bugreports.qt.io/browse/QTBUG-6345
Based on the statement by Thiago Macieira, "Sorry, we will not support building Qt like this," I've been worried that fixing Qt to work like everything else might caus开发者_如何学Pythone some problem and have been trying to avoid it. We recompiled all of our support libraries with the /Zc:wchar_t- flag and have been fairly content with that until a couple days ago when we started trying to port over (we're in the process of switching from Wx to Qt) some serialization code.
Because of how win32 works, and because Wx just wraps win32, we've been using std::wstring
to represent string data with the intent of making our product as i18n ready as possible. We did some testing and Wx did not work with multibyte characters when trying to print special stuff (even not so special stuff like the degree symbol was an issue). I'm not so sure that Qt has this problem since QString isn't just a wrapper to the underlying _TCHAR type but is a Unicode monster of some sort.
At any rate, the serialization library in boost has compiled parts. We've attempted to recompile boost with /Zc:wchar_t- but so far our attempts to tell bjam to do this have gone unheeded. We're at an impasse.
From where I'm sitting I have three options:
Recompile Qt and hope it works with /Zc:wchar_t. There's some evidence around the web that others have done this but I have no way of predicting what will happen. All attempts to ask Qt people on forums and such have gone unanswered. Hell, even in that very bug report someone asks why and it just sat there for a year.
Keep fighting with bjam until it listens. Right now I've got someone under me doing that and I have more experience fighting with things to get what I want but I do have to admit to getting rather tired of it. I'm also concerned that I'll KEEP running into this issue just because Qt wants to be a c**t.
Stop using wchar_t for anything. Unfortunately my i18n experience is pretty much 0 but it seems to me that I just need to find the right to/from function in QString (it has a BUNCH) to encode the Unicode into 8-bytes and visa-versa. UTF8 functions look promising but I really want to be sure that no data will be lost if someone from someplace with a more symbolic language starts writing in their own language and the documentation in QString frightens me a little into thinking that could happen. Of course, I could always run into some library that insists I use wchar_t and then I'm back to 1 or 2 but I rather doubt that would happen.
So, what's my question...
Which of these options is my best bet? Is Qt going to eventually cause me to gouge out my own eyes because I decided to compile it with /Zc:wchar_t anyway?
What's the magic incantation to get boost to build with /Zc:wchar_t- and will THAT cause permanent mental damage?
Can I get away with just using the standard 8-bit (well, 'common' anyway) character classes and be i18n compliant/ready?
How do other Qt developers deal with this mess?
I would agree with Öö Tiib's remark
That option is perhaps for compatibility with some old legacy pre-wchar_t code.
Having in mind that Qt is ported to many different platforms (including embedded systems), some of them not having a decent C++ compiler, I would guess that this switch is just to make it possible to compile Qt on those platforms. I mean it's probably not something that Qt relies on to work correctly. If it were the case it would mean that Qt's design is deeply broken in my opinion. So option 1 should work.
Having said that I would definitely recommend choosing option 3 because
wchar_t
gives you almost nothing in regard to i18n- as you noticed Qt has very capable string class which makes i18n an easy task (see Internationalization with Qt)
You might take a look at results of searching for wchar_t
on qt-interest@qt.nokia.com list, ask your question there and talk to Thiago Macieira on freenode.net #qt irc channel where Thiago is very active.
Stumbled over the same issue ...
Obviously bjam expects cxxflags=-Zcwchar_t-
After building the static serialization libs via
bjam --with-serialization toolset=msvc-8.0 variant=debug threading=multi link=static cxxflags=-Zc:wchar_t-
everything linked like expected.
Hope this helps anyone.
Putting this here as an answer because it's too long for comment.
Here's one of the answers to why one might be getting LNK2019 aka "symbol not found" linker error (source):
- You mix code that uses native wchar_t with code that doesn't. C++ language conformance work that was done in Visual C++ 2005 made
wchar_t a native type by default. You must use the /Zc:wchar_t-
compiler option to generate code compatible with modules compiled by
using earlier versions of Visual C++. If not all modules have been
compiled by using the same /Zc:wchar_t settings, type references may
not resolve to compatible types. Verify that wchar_t types in all
modules are compatible, either by updating the types that are used,
or by using consistent /Zc:wchar_t settings when you compile.
So that could be the main reason why /Zc:wchar_t- is there in all cl.exe-related mkspec files and also why you probably don't need it.
I like having native wchar_t
because it makes it sometimes easy to convert between the strings that the windows api expects and QString.
wchar_t should be type like bool or long. No headers are needed to define it.
You did use that "wchar_t is undefined type" option. Then you typedef wchar_t as unsigned short and then you wonder that nothing works anymore?
That option is perhaps for compatibility with some old legacy pre-wchar_t code. Just simply ... never use it. Otherwise nothing C++ links to it because functions that take wchar_t parameters are differently name-mangled than functions that take unsigned short parameters.
If some library is compiled with some strange options then build it with correct options. When needed then fix its code. If you can not do it then you should not use that library. Every line of code in your C++ project is yours to maintain.
精彩评论