In Qt, how to setCodecForCStrings globally (in hea

2019-07-29 17:05发布

I'm developing a bunch of Qt applications in C++ and they all use some modules (translation units) for common functionality that use Qt as well.

Whenever I convert a C string (implicit conversion) or C++ string object (fromStdString()) to a QString object, I expect the original data to be UTF-8 encoded and vice versa (toStdString()).

Since the default is Latin-1, I have to set the codec "manually" (in the init procedure of every one of my programs) to UTF-8:

QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf8"));

Not all of my modules have an init procedure. The ones containing a class do (I can put this line in the class constructor), but some modules just contain a namespace with lots of functions. So there's no place for setCodecForCStrings(). Whenever I convert from/to a QString implicitly (from within one of my modules), I rely on the codec being already set by the init procedure of the main program, which seems to be a rather bad solution.

Is there a reliable way to set the codec to UTF-8 in my modules, or will I just have to be very careful not to use implicit conversions at all (in my modules at least) and write something like std::string(q.toUtf8().constData()) instead of q.toStdString()?

标签: qt utf-8 qstring
1条回答
Juvenile、少年°
2楼-- · 2019-07-29 17:37

This can be done using a class definition for an automatically instantiated singleton-similar class having some init code in its constructor:

class ModuleInit {
    static ModuleInit *instance;
public:
    ModuleInit() {
        QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf8"));
    }
};
ModuleInit * ModuleInit::instance = new ModuleInit(); // put this line in .cpp!

Putting this code anywhere into any project will set the text codec to UTF-8. You can, however, overwrite the text codec in the main() method, since the code above is executed even before the main() method.

With "anywhere" I of course mean places where it is syntactically allowed to. Put the class definition in some header file, and the instantiation in the appropriate .cpp file.

You can even put the whole code in one .cpp file, say moduleinit.cpp which you compile and link, but never explicitly use (there is no header file you could include...). This will also avoid accidental instantiations except the very first one and you will not have any problems with duplicate class names.

Note that you can't set the codec for C-strings in one particular file. Setting the codec using QTextCodec::setCodecForCString will set it application-wide!

查看更多
登录 后发表回答