Qt宏Q_OBJECT展开记录



  • c++中的宏

    #define A 3.14 展开后把A替换为B

    #define A(a) #a 展开后用a的字符串替换A(a)

    #define A(a) a##B 展开后把a和B的字符串连接起来后替换A(a)

    #include "common/common.h"
    #define PI 3.14
    #define PIPrivate 3.1415
    #define foo(arg) #arg
    #define bar(arg) arg##Private
    int main(int argc, char *argv[]) {
    
        DApplication::loadDXcbPlugin();
        DApplication app(argc, argv);
        Dtk::Util::DLogManager::registerConsoleAppender();
        Dtk::Util::DLogManager::registerFileAppender();
        qDebug()<<PI<<foo(PI)<<bar(PI)<<foo(bar(PI));
        return 0;
    }
    
    

    源码地址:GitHub

    在Qt中,用了不少的宏。最常见的就是Q_OBJECT

    Q_OBJECT展开的最终效果如下

    public:
        template<typename ThisObject>
        inline void qt_check_for_QOBJECT_macro(const ThisObject &_q_argument) const {
            int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument);
            i = i + 1;
        }
        _Pragma(GCC diagnostic push)
        static const QMetaObject staticMetaObject;
        virtual const QMetaObject *metaObject() const;
        virtual void *qt_metacast(const char *);
        virtual int qt_metacall(QMetaObject::Call, int, void **);
        static inline QString tr(const char *s, const char *c = Q_NULLPTR, int n = -1) {
            return staticMetaObject.tr(s, c, n);
        }
    
        static inline QString trUtf8(const char *s, const char *c = Q_NULLPTR, int n = -1) {
            return staticMetaObject.tr(s, c, n);
        }
    private:
        __attribute__((visibility("hidden"))) static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
        _Pragma(GCC diagnostic pop)
        struct QPrivateSignal {};
    

    下面做一步步展开
    Q_OBJECT展开后如下,又有不少的宏

    public: 
        Q_OBJECT_CHECK 
        QT_WARNING_PUSH 
        Q_OBJECT_NO_OVERRIDE_WARNING 
        static const QMetaObject staticMetaObject; 
        virtual const QMetaObject *metaObject() const; 
        virtual void *qt_metacast(const char *); 
        virtual int qt_metacall(QMetaObject::Call, int, void **); 
        QT_TR_FUNCTIONS 
    private: 
        Q_OBJECT_NO_ATTRIBUTES_WARNING 
        Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); 
        QT_WARNING_POP 
        struct QPrivateSignal {}; 
        QT_ANNOTATE_CLASS(qt_qobject, "")
    

    Q_OBJECT_CHECK展开如下,宏越来越多了。

    template<typename ThisObject>
    inline void qt_check_for_QOBJECT_macro(const ThisObject &_q_argument) const {
        int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument);
        i = i + 1;
    }
    

    QT_WARNING_PUSHQT_WARNING_POP展开

    #define QT_WARNING_PUSH QT_DO_PRAGMA(GCC diagnostic push)
    #define QT_WARNING_POP QT_DO_PRAGMA(GCC diagnostic pop)
    

    QT_DO_PRAGMA展开

    #define QT_DO_PRAGMA(text)                      _Pragma(#text)
    

    又来了新的宏_Pragma,参考2.1.3 _Pragma操作符,就是告诉编译器GCC diagnostic push

    Q_OBJECT_NO_OVERRIDE_WARNING展开

    #if defined(Q_CC_CLANG) && Q_CC_CLANG >= 306
    #  define Q_OBJECT_NO_OVERRIDE_WARNING      QT_WARNING_DISABLE_CLANG("-Winconsistent-missing-override")
    #else
    #  define Q_OBJECT_NO_OVERRIDE_WARNING
    #endif
    
    

    QT_TR_FUNCTIONS展开,QT_DEPRECATED展开为空

    static inline QString tr(const char *s, const char *c = Q_NULLPTR, int n = -1) {
        return staticMetaObject.tr(s, c, n);
    }
    
    QT_DEPRECATED static inline QString
    trUtf8(const char *s, const char *c = Q_NULLPTR, int n = -1) {
        return staticMetaObject.tr(s, c, n);
    }
    

    Q_OBJECT_NO_ATTRIBUTES_WARNING展开,QT_WARNING_DISABLE_GCC展开为空

    #define Q_OBJECT_NO_ATTRIBUTES_WARNING QT_WARNING_DISABLE_GCC("-Wattributes")
    

    Q_DECL_HIDDEN_STATIC_METACALL展开,出现了__attribute__黑魔法,参考ATTRIBUTE 你知多少?

    #define Q_DECL_HIDDEN_STATIC_METACALL Q_DECL_HIDDEN
    #define Q_DECL_HIDDEN     __attribute__((visibility("hidden")))
    

    QT_ANNOTATE_CLASS展开为空

    #define QT_ANNOTATE_CLASS(type, ...)
    

    参考文章
    2.1.3 _Pragma操作符
    ATTRIBUTE 你知多少?

    源码地址:GitHub



  • @大黄老鼠 宏魔法真心黑啊



  • @大黄老鼠 因为GCC大家庭主要使用的是__attribute__修饰。
    而MSVC可以在类名或者函数名前面修饰。比如说__stdcall__declspec(dllexport)



  • @jiangcaiyang c++各种黑魔法,我怀恋java



  • @大黄老鼠Qt宏Q_OBJECT展开记录 中说:

    GitHub

    能变出钱来的魔法就是好魔法,人家用易语言的也有发了大财的。



  • @stlcours 支持一个。不管用什么语言,不断完善自己的产品才是正确的道路。


 

最近的回复

  • 随后在git for windows这个软件中输入

    git clone git@git.coding.net:jiangcaiyang1/qtdreamrelease_windows.git

    就可以获得一个空的项目了。其它的项目也是同样的操作方法。然后呢,将此作为自动构建的代码库吧。
    此次介绍就是这样~😘 😘 🐧

    阅读更多
  • 0_1540027445466_很好.jpg
    萌梦安装包的分发始终是一个难题。要有一个稳定并且有效的方法进行分包,才能让大家都能够享受到萌梦动作编辑器的最新功能。我们目前有两种分发的方法:

    离线安装包。通常的位置是
    1.1 百度云盘
    1.2 QQ群文件
    1.3 github
    其中百度云盘和QQ群文件不会定期地更新,只有github的文件会定期更新。因为构建脚本要求每次有更改,都让github的文件更新。

    在线安装包。通常的位置是
    2.1 百度云盘
    2.2 QQ群文件
    2.3 github
    这里在线安装包的代码库主要还是在github中,在线安装包非常依赖CDN加速。目前github这块儿在国内做得不太好,还是希望在国内找一个类似的加速。目前可以选的只有两家:

    码云

    coding

    因为以前做过coding的加速,目前coding已经和腾讯云战略合作,所有的代码都要迁移到腾讯云了。而且对于代码库的空间要求变高了。128M。目前我的一个账号显然满足不了要求。所以有必要再注册一个账号。

    下面记录一下新建coding代码库的方法,并且尝试将萌梦安装包的线上代码库部分移动到coding代码库中。

    注册

    到这个位置注册。

    https://coding.net/register

    相信很快就会带你跳转到腾讯云中。不过这里我选择的是邮箱的方式,因为我希望注册尽量多的账号。

    设置ssh密钥

    进入控制台后,是这样的:
    0_1540028446495_2eeb7e93-c15b-4c82-9b36-58e1c304ea3f-image.png
    这个时候,我们要先创建项目,然后ssh的公钥。
    0_1540028822318_b3e81b93-099c-42d5-820d-deaf8d445913-image.png

    创建以后,开始部署公钥。在这里:
    0_1540028925337_d8059b64-8535-45e5-ba4c-d7454505aa5a-image.png
    这期间最好用OpenSSL生成SSH密钥。
    我使用的是git for windows来生成密钥的。方法是

    ssh-keygen

    如果你生成好了密钥,可以直接打开密钥内容看看:

    cat ~/.ssh/id_rsa.pub

    然后粘贴到网站的文本框中。

    添加好了之后,勾选“准许推送权限”,需要推送代码到代码库中。

    阅读更多

关注我们

微博
QQ群











召唤伊斯特瓦尔