1. 程式人生 > >Qt Creator外掛製作小插曲:有關QT_NO_CAST_FROM_ASCII的注意事項

Qt Creator外掛製作小插曲:有關QT_NO_CAST_FROM_ASCII的注意事項

這兩天製作了兩個Qt Creator增強套裝的兩個外掛,其實也是非常簡單的,但是其實花了我超過四天的時間,為什麼呢?因為我之前很長一段時間都是在Linux下開發的,一切安好,沒有任何問題,但是到了Windows下,各種問題就暴露出來了。首先呢,就是——

1、Qt Creator原始碼中,預設是開啟QT_NO_CAST_FROM_ASCII這個巨集的,看文件,這個巨集就是禁用一切來自雙引號或者單引號的字串字面量傳入QString的函式。但是我們裸寫字串不是非常平常的一件事情麼?這裡是Qt Creator斷了我們一條道路,解決的方法還是有的,我這裡提供兩個方法,歡迎提出新的方法:
1) 在

include($$QTCREATOR_SOURCES/src/qtcreatorplugin.pri)

這一句後面新增

DEFINES -= QT_NO_CAST_FROM_ASCII

如果還有必要的話,那麼還需要新增

DEFINES -= QT_NO_CAST_TO_ASCII

這些都是解除設定巨集的好方法

2) 使用QStringLiteral巨集來包裹字面量
我還設計了兩個巨集,分別對應識別單個字元和字串。他們分別是:

#define CHAR( c ) QChar( ushort( c ) )
#define TEXT QStringLiteral

這些都是非常方便的巨集,可以很方便地替換掉裸寫的字面量。

2、由於Windows下編譯器有MinGW以及MSVC,我們要注意我們編寫的外掛是C++外掛,是編譯器相關的,比如說,MinGW編寫的外掛無法在MSVC編譯器編譯的Qt Creator上使用。遺憾的是,Qt Creator官方編譯的都是MSVC的,而且有一個現象,不同的MSVC版本編寫的Qt Creator依賴的Qt庫,有一些函式的地址還不能通用。比如說和上面一個例子非常相似的例子,那就是我使用MSVC2015編譯的Qt Creator外掛,其中用到了QString::utf8()函式,但就是這個函式,無法在官方MSVC2013編譯的Qt Creator中成功載入,提示“無法找到模組”。為什麼呢?看看QString::utf8()函式原始碼吧:

#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP)
    QByteArray toLatin1() const & Q_REQUIRED_RESULT
    { return toLatin1_helper(*this); }
    QByteArray toLatin1() && Q_REQUIRED_RESULT
    { return toLatin1_helper_inplace(*this); }
    QByteArray toUtf8() const & Q_REQUIRED_RESULT
    { return toUtf8_helper(*this); }
    QByteArray toUtf8() && Q_REQUIRED_RESULT
    { return toUtf8_helper(*this); }
    QByteArray toLocal8Bit() const & Q_REQUIRED_RESULT
    { return toLocal8Bit_helper(constData(), size()); }
    QByteArray toLocal8Bit() && Q_REQUIRED_RESULT
    { return toLocal8Bit_helper(constData(), size()); }
#else
    QByteArray toLatin1() const Q_REQUIRED_RESULT;
    QByteArray toUtf8() const Q_REQUIRED_RESULT;
    QByteArray toLocal8Bit() const Q_REQUIRED_RESULT;
#endif

看出來什麼嗎?不同的預編譯巨集會導致不同版本的toUtf8()函式被編譯,難怪Qt Creator發現QString::utf8()函式和自己Qt庫中的這個函式地址不一致會報“無法找到模組”錯誤呢。

那,有沒有解決的方法呢?由於Json格式化,一定要這樣的函式,因此我打算看看它的原始碼,是否能夠找到替代的實現方法。沒錯,就是

toUtf8_helper(*this);

中,我找到了

QUtf8::convertFromUnicode()

方法
終於找到了這個方法,又偶然發現QTextCodec::fromUnicode()函式中隱含呼叫了上述函式,於是我這麼操作:

    QTextCodec* utf8Codec = QTextCodec::codecForName( "UTF-8" );

    QString plainText = ui->jsonEdit->toPlainText( );
    QByteArray converted = QJsonDocument::fromJson( utf8Codec->fromUnicode( plainText ) ).
            toJson( QJsonDocument::Indented );
    plainText = utf8Codec->toUnicode( converted );

順利實現效果!

開發Qt Creator的過程中,每一步都是一個坑。但萬變不離其宗,只要你有耐心,找到規律,找到核心問題,相信你一定和我一樣,最終會找到問題的答案的。