精华内容
下载资源
问答
  • moc文件解析

    2021-03-08 16:43:45
    参考 详细分析Qt中moc文件 2.MOC文件解读(上)——MOC文件中的数据 3.MOC文件解读(下)——MOC文件中的函数 C 库宏 -offsetof()
    展开全文
  • 宏Q_OBJECT中的数据部分已经在在上一篇https://blog.csdn.net/Master_Cui/article/details/109007524分析完了,但是,MOC文件中还有一部分函数也在MOC文件中实现 对应的函数如下 virtual const QMetaObject *...

    宏Q_OBJECT中的数据部分已经在在上一篇https://blog.csdn.net/Master_Cui/article/details/109007524分析完了,但是,MOC文件中还有一部分函数也在MOC文件中实现

    对应的函数如下

     virtual const QMetaObject *metaObject() const; \
     virtual void *qt_metacast(const char *); \
     virtual int qt_metacall(QMetaObject::Call, int, void **); \
     Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \

    除了上面的虚函数外,还有两个信号函数,由MOC实现

    // SIGNAL 0
    void moctest::sigf1(double _t1)
    {
        void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
        QMetaObject::activate(this, &staticMetaObject, 0, _a);
    }
    
    // SIGNAL 1
    int moctest::sigf2(char _t1, int _t2)
    {
        int _t0{};
        void *_a[] = { const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t0))), const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))), const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t2))) };
        QMetaObject::activate(this, &staticMetaObject, 1, _a);
        return _t0;
    }

    两个信号函数代码都是先定义一个void*的指针数组,数组的第一个元素都是空,给元对系统内部注册元方法参数类型时使用,剩下的元素都是信号函数的参数的指针,然后将数组传入activate

     

    virtual const QMetaObject *metaObject() const; 的实现

    const QMetaObject *moctest::metaObject() const
    {
        return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
    }

    一般情况下,QObject::d_ptr->metaObject总为空,此时返回MOC文件中的数据staticMetaObject的地址,当使用qml编写界面程序时,会返回QObject::d_ptr->dynamicMetaObject()

     

    virtual void *qt_metacast(const char *); 的实现

    void *moctest::qt_metacast(const char *_clname)
    {
        if (!_clname) return nullptr;
        if (!strcmp(_clname, qt_meta_stringdata_moctest.stringdata0))
            return static_cast<void*>(this);
        return QObject::qt_metacast(_clname);
    }

    这个函数首先判断字符串的指针是否为空,然后将字符串和MOC文件中表示类名的字符串进行比较,如果字符串内容是当前的类名,那么将当前对象的地址转为void*并返回,否则调用基类的qt_metacast,这个过程一直迭代到根上的基类 QObject::qt_metacast(_clname) 为止,如果 _clname 不在类的继承树上,那么返回值就是空。

     

    virtual int qt_metacall(QMetaObject::Call, int, void **);的实现

    int moctest::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
    {
        _id = QObject::qt_metacall(_c, _id, _a);
        if (_id < 0)
            return _id;
        if (_c == QMetaObject::InvokeMetaMethod) {
            if (_id < 5)
                qt_static_metacall(this, _c, _id, _a);
            _id -= 5;
        } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
            if (_id < 5)
                *reinterpret_cast<int*>(_a[0]) = -1;
            _id -= 5;
        }
        return _id;
    }

    其中QMetaObject::Call是个枚举,在qobjectdefs.h中,枚举的定义如下:

    enum Call {
            InvokeMetaMethod,
            ReadProperty,
            WriteProperty,
            ResetProperty,
            QueryPropertyDesignable,
            QueryPropertyScriptable,
            QueryPropertyStored,
            QueryPropertyEditable,
            QueryPropertyUser,
            CreateInstance,
            IndexOfMethod,
            RegisterPropertyMetaType,
            RegisterMethodArgumentMetaType
        };

    InvokeMetaMethod 代表元方法调用,比如信号槽的调用。

    然后从 ReadProperty 到 QueryPropertyUser ,是属性操作相关的。

    CreateInstance 是用元构造函数生成新实例的调用方式。

    IndexOfMethod qt_static_metacall()会根据这个调用方式,查询匹配的信号函数的相对序号。基类和当前类都有一大堆元方法,这些所有的元方法都有它的绝对序号和相对序号,绝对序号是从顶层基类 QObject 开始计数,相对序号从当前类开始计数。

    RegisterPropertyMetaType是注册属性类型的调用方式

    RegisterMethodArgumentMetaType是注册元方法参数类型的调用方式,与 qt_meta_data_moctest 数组元方法参数类型条目中信号槽参数(

    // signals: parameters
    QMetaType::Void, QMetaType::Double,    2,
    QMetaType::Int, QMetaType::Char, QMetaType::Int,    2,    2,
    
     // slots: parameters
     QMetaType::Void, QMetaType::Double,    2,
     QMetaType::Int, QMetaType::Char,    2,
     QMetaType::Bool, QMetaType::Char,    2,

    )对应。

     

    对于信号槽的调用,_id 是元方法的绝对序号, _a 在信号函数里被封装,和信号函数中的_a对应

    接着调用基类的qt_metacall

    _id = QObject::qt_metacall(_c, _id, _a);

    该方法的主要作用是重新获得信号槽的相对序号_id

    然后

       if (_id < 0)
            return _id;//如果相对序号_id<0,说明被调用的信号槽不在当前的对象中,直接返回
        if (_c == QMetaObject::InvokeMetaMethod) {//要调用信号槽
            if (_id < 5)//被调用的信号槽在当前的对象中,调用qt_static_metacall对信号槽进行调用
                qt_static_metacall(this, _c, _id, _a);
            _id -= 5;//刷新id_
        } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {//如果是要对信号槽的参数进行匹配检查
            if (_id < 5)//被调用的信号槽在当前的对象中
                *reinterpret_cast<int*>(_a[0]) = -1;//将指针数组的第一个元素值为-1,表示匹配检查过了
            _id -= 5;
        }
        return _id;

    所以,这个函数的作用就是:1、发起对信号槽函数的调用。2、对信号槽函数进行参数检查

     

    static void qt_static_metacall的实现

    void moctest::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
    {
        if (_c == QMetaObject::InvokeMetaMethod) {
            auto *_t = static_cast<moctest *>(_o);//将_o转化为当前对象的指针
            Q_UNUSED(_t)
            switch (_id) {//然后根据相对序号_id调用具体的信号槽函数
            case 0: _t->sigf1((*reinterpret_cast< double(*)>(_a[1]))); break;
            case 1: { int _r = _t->sigf2((*reinterpret_cast< char(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])));
                if (_a[0]) *reinterpret_cast< int*>(_a[0]) = std::move(_r); }  break;//如果信号槽函数有返回值,将返回值保存到指针数组的第一个元素指向的对象中
            case 2: _t->slotf((*reinterpret_cast< double(*)>(_a[1]))); break;
            case 3: { int _r = _t->slotf2((*reinterpret_cast< char(*)>(_a[1])));
                if (_a[0]) *reinterpret_cast< int*>(_a[0]) = std::move(_r); }  break;
            case 4: { bool _r = _t->slotf3((*reinterpret_cast< char(*)>(_a[1])));
                if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = std::move(_r); }  break;
            default: ;
            }
        } else if (_c == QMetaObject::IndexOfMethod) {//如果是信号序号的查询调用,在QT5中,connect前必须检查信号是否为函数指针,然后在做关联,然后在_a[0]中可以知道
            int *result = reinterpret_cast<int *>(_a[0]);//先取得指针数组第一个元素的地址
            {
                using _t = void (moctest::*)(double );
                if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&moctest::sigf1)) {//判断信号函数的类型与_t是否一致
                    *result = 0;//如果一致,将result指向的内容变为信号的相对序号
                    return;
                }
            }
            {
                using _t = int (moctest::*)(char , int );
                if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&moctest::sigf2)) {
                    *result = 1;
                    return;
                }
            }
        }
    }

    至此,MOC文件中的代码解析完毕,然后,信号槽得需要connect进行连接,后面会解析connect函数

     

    参考

    Qt5.14源码

    https://qtguide.ustclug.org/

     

    欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

    展开全文
  • moc文件的作用

    千次阅读 2016-01-07 09:02:52
    moc文件的作用之一:生成信号。 在某个类的头文件中,定义了一个信号后,在该类的moc文件中,会把该信号生成为一个函数。 qt认识的是 moc文件中的信号函数,而不是,类头文件中的信号定义。 所以,如果...

    moc文件的作用之一:生成信号。


    在某个类的头文件中,定义了一个信号后,在该类的moc文件中,会把该信号生成为一个函数。

    qt认识的是 moc文件中的信号函数,而不是,类头文件中的信号定义。


    所以,如果编译程序的时候,报错说某个信号没有定义。

    那么首先看下,该信号是否在头文件中定义了。

    其次看下,该类的moc文件是否生成了。

    moc文件都在GenerateFiles文件夹下面。

    展开全文
  • 一、什么时候需要生成moc文件 当我们在test.h中使用Q_OBJECT宏定义时,需要使用Qt提供的moc.exe将test.h编译为moc_test.cpp,当编译为moc后,一般还需要在test.cpp中末尾处,添加一句#include "moc_test.cpp" 二、...

    一、什么时候需要生成moc文件

    当我们在test.h中使用Q_OBJECT宏定义时,需要使用Qt提供的moc.exe将test.h编译为moc_test.cpp,当编译为moc后,一般还需要在test.cpp中末尾处,添加一句#include "moc_test.cpp"

    二、怎样生成moc文件

    利用Qt安装目录下的moc.exe,比如:D:\Qt\Qt5.13.0\5.13.0\msvc2017_64\bin\moc.exe,即可生成moc。

    生成命令:

    moc.exe test.h -o moc_test.cpp
    

    三、在VS中如何生成moc文件

    一般在VS工程下,会有很多个源文件,VS允许我们对每个文件添加“自定义生成工具”。意思就是说,允许每个文件使用我们指定的编译方式。

    这里我们,可以给需要生成moc的头文件,指定使用moc来进行编译。

    在VS2017中,为源文件添加自定义生成工具,步骤如下:

    (1) 选择“xxx.h”文件,右键选择“属性”->“配置属性”->“常规”->“项类型”,选择“自定义生成工具”;
    (2) 点击“应用”,左边导航树中会新增一个条目“自定义生成工具”,展开它,选择下面的“常规”,分别填写如下3条内容;

    在这里插入图片描述

    这3条内容的含义,如下:

    • 命令行
    $(MOC) "%(FullPath)" -o "%(Filename)".moc
    

    翻译过来,就是形如

    moc.exe test.h -o test.moc
    

    表示使用moc.exe将.h编译为moc文件。

    • 说明
    Moc%27ing %(FullPath)
    

    就是VS编译该文件时,在输出窗口打印的信息,比如,编译test.h时,就会打印如下

    Moc'ing D:\xx\yy\test.h
    
    • 输出
    %(Filename).moc
    

    表示编译之后生成moc文件名称。

    注意:

    $(MOC)宏,表示moc.exe的路径,需要先进行添加后,再使用。



    若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!

    同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。

    在这里插入图片描述

    展开全文
  • 详细分析Qt中moc文件

    千次阅读 2018-11-24 11:34:50
    详细分析Qt中moc文件  一直想写一片详细分析Qt中moc文件的文章,今天终于是完成了。迫不及待的分享给大家,希望大家可以赏个脸,认真的看完,希望对大家的学习也有帮助。请看下面的分析Qt中moc文件的详细内容。  ...
  • moc文件 如何生成的

    千次阅读 2016-01-07 08:59:51
    如果发现某个类的moc文件没有生成,或者 发现某个类的moc文件,没有出现在GenerateFiles文件夹下面,而是出现在了SourceFiles文件下面。 那么,出现两种问题的原因就是:解决冲突的时候,*.vcproj文件出错了。 ...
  • 手动生成MOC文件

    2014-03-12 11:06:48
    一直以来我都是将moc命令写成批处理文件,并且一直使用很正常,今早来要为一个类生成moc文件,批处理是直接由以前正常运行的批处理文件改成,应该是没有什么错误的,其结果却发现我所要的moc文件并没有生成.原始头文件...
  • Qt自动生成moc文件

    万次阅读 2013-08-16 13:25:19
    命令行生成moc文件的方式: cd C:/Qt/4.7.1/bin moc .h文件群路径 -o 要生成的moc文件的全路径; 例如: VS中不是用addin创建的项目,自动生成moc文件的设置: 在VS的解决方案管理器里面,右键需要生成...
  • Qt与VS生成Moc文件

    2019-12-02 14:56:06
    1.选择没有生成moc文件的头文件,右键,点击属性,在配置属性中选择常规,将项类型修改为“自定义生成工具”: 2.修改自定义生成工具--常规中的“命令行”和“输出”两项: 命令行: "$(QTDIR)\bin\moc.exe" "%...
  • 在抓包之后,发现是.moc文件没有成功获取,反而出现了404错误。经过认真的检查之后,发现路径并没有存在错误,对于相同路径下的.js文件.css文件等都可以正常地获取,只有.moc文件没办法正常获取。 一开始我以为是...
  • 只有头文件(*.h)中包含了Q_OBJECT宏的时候,不管这个宏的位置在文件中的哪里,qmake *.pro生产的makefile文件中才会出现moc文件的依赖项(即使用make命令可以自动生成moc文件),如果Q_OBJECT包含在cpp文件中,则需要...
  • 当在VS工程中编写QT和C++程序时,要想不同模块之间通过QT的信号(SIGNALS)和槽(SLOT)的机制进行通信,就需要继承于QOBJECT基类,继承于QOBJECT基类的类(文件),会相应的生成一个moc文件,若没有生成moc文件,则...
  • moc_QtMqttclient.cpp:52: error: no 'void QtMqttclient::qt_static_metacall(QObject*, QMetaObject:...在linux上编译没有报错,但是在进行交叉编译的时候却报错了,moc文件不是自动生成的吗,为啥会出现这样的问题啊
  • 直接打开别人写的VS+QT程序,编译后提示没有moc文件,解决后觉得问题比较low.用QT TOOL project编译程序会生成MOC 但是给一些刚入门的借鉴    
  • 使用VS的Qt插件进行Qt开发时,有时候会遇到不能生成moc文件的问题。   1.在工程中可以看到这个Generated files目录下是有一个看似moc文件的文件,双击打开的话: 如果能正常打开,文件就能正常使用。 2.选中...
  • 当在VS工程中编写QT和C++程序时,要想不同模块之间通过QT的信号(SIGNALS)和槽(SLOT)的机制进行通信,就需要继承于QOBJECT基类,继承于QOBJECT基类的类(文件),会相应的生成一个moc文件,若没有生成moc文件,则...
  • 在使用QT的信号槽机制时,moc.exe会根据类头文件生成对应的... 解决方法,找到对应类头文件右键,打开属性页面,在moc.exe参数prepend中加入预编译头stdafx.h,重新编译项目,moc就会自动加入stdafx.h到moc文件中了...
  • 已经尝试的解决方法,重新生成QT5.9.4的moc文件替换掉原来老的moc文件,加载进VS工程,重新生成解决方案,仍旧出现无法解析的命令,关于UI界面的所有类如QLabel,QWidgets,QRadioButton等均报错,无法解析的外部...
  • 在工程中可以看到这个Generated files目录下是有一个看似moc文件的文件,双击打开的话: 第二步: 双击打开的话,会弹出这个窗口,说文件不存在或者删除了: 第三步: 选中没有生成moc文件的头文件,鼠标...
  • 碰到此类问题,一般都是对应的.h文件没有在generate file文件夹下自动生成对应的moc_filename.h所致。网上有很多关于这方面的答案,大致过程无外乎两种: ...那就用第二种方法,可是全部修改后,moc文件...
  • Qt工程没有对应生成moc文件

    千次阅读 2018-01-23 12:50:27
    但是,代码粘过来,设置好工程属性,生成解决方案时,却说无法打开我的工程里某个头文件的对应的moc文件, 即GeneratedFiles\Debug\moc_xxxxxxxx,我对应打开工程的这个文件,真的没找到,后开百度到,有人也有类似...
  • 好像一般的MOC文件的tag标志都是2,没啥特殊意义 第五列数据表示信号槽函数标志位,在qmetaobject_p.h 里声明,声明如下 enum MethodFlags { AccessPrivate = 0x00, AccessProtected = 0x01, AccessPublic = 0x02, ...
  • 点击不生成moc文件的.h文件,点击属性,进行如下修改 然后打开.h文件,查看是否添加Q_OBJECT 然后清理,重新生成就OK了
  • VS+Qt5生成moc文件

    千次阅读 2015-11-12 09:57:54
    1.选择没有生成moc文件的头文件,右键,点击属性 2.在配置属性中选择常规,将项类型修改为“自定义生成工具” 3.修改自定义生成工具--常规中的“命令行”和“输出”两项 命令行:"$(QTDIR)\bin\moc.exe" "%...
  • 生成的类都生成在MOC文件中了,请问要怎么设置回来? 切换为其他项目的时候倒是没问题 <p style="text-align:center"><img alt="" height="166" src=...
  • 在vs中编写c++代码,想利用qt的信号槽机制,库和头文件都具备,但是编译链接报错,发现没有moc文件。 选中没有生成moc文件的头文件,鼠标右键选择属性,如下图所示: 在属性页,可以看到General-&gt;...
  • moc文件生成方法

    千次阅读 2018-08-01 16:12:05
    下面给出例子手动生成moc的例子:   1、首先在运行窗口中输入cmd   2、在cmd中输入:cd C:\Qt\4.7.4\bin进入Qt安装目录,如下图:   3、输入:moc "E:\03 Code\QUnitTest\DlgFindDialog.h" -...
  • moc文件问题

    2017-08-24 18:04:45
    右键转到自动槽的时候发生的问题,请问...手动删除moc文件好像可以解决,但我不知道如何手动删除moc文件。 好郁闷,改了两个button的名字让ui找不到cpp文件了,对了,这两个button都是有自动槽的。 菜鸟求教了。。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 755
精华内容 302
关键字:

moc文件