Qt/Qt Quick宏浅议一文中,我们将介绍Qt中经常使用的几个宏: Q_OBJECT, SIGNAL与SLOT, Q_SIGNALS 与 Q_SLOTS, Q_EMIT ,Q_INVOKABLE, Q_PROPERTY。相比其他宏,Q_INVOKABLE 显得更加神秘,但Q_INVOKABLE的理解与使用变得越来越重要。本文将围绕Q_INVOKABLE以及相对应的invokeMethod展开讨论。

Q_INVOKABLE

#define Q_INVOKABLE

重新回顾一下Q_INVOKABLE的定义,它在$QTDIR/src/corelib/kernel/qobjectdefs.h 中,简单被define,目的在于让moc识别。

使用Q_INVOKABLE来修饰成员函数,目的在于被修饰的成员函数能够被元对象系统所唤起。

QMetaObject::invokeMethod

静态方法QMetaObject::invokeMethod() 的定义如下:

  1. bool QMetaObject::invokeMethod ( QObject * obj, const char * member,Qt::ConnectionType type,
  2. QGenericReturnArgument ret, QGenericArgument val0 = QGenericArgument( 0 ), …)

invokeMethod的用法为,尝试调用对象obj的方法member(注意member可以为信号或者是槽),如何member可以被调用,则返回真,否则返回假。QMetaObject::invokeMethod可以是异步调用,也可以是同步调用。这取决与它的连接方式Qt::ConnectionType type。如果type为Qt::DirectConnection,则为同步调用,若为Qt::QueuedConnection,则为异步调用。例如:

  1. QMetaObject::invokeMethod(object, "methodName",
  2. Qt::QueuedConnection,
  3. Q_ARG(type1, arg1),
  4. Q_ARG(type2, arg2));

上述调用为异步调用。请注意,因为上面所示的参数需要被在构建事件时进行硬拷贝,参数的自定义型别所对应的类需要提供一个共有的构造函数、析构函数以及拷贝构造函数。而且必须使用注册Qt型别系统所提供的qRegisterMetaType() 方法来注册这一自定义型别。

Q_INVOKABLE与QMetaObject::invokeMethod均由元对象系统唤起。这一机制在Qt C++/QML混合编程跨线程编程Qt Service Framework 以及 Qt/ HTML5混合编程以及里广泛使用。

Qt C++/QML混合编程

QML中调用C++方法借助了Qt元对象系统。考虑在QML中使用Qt C++定义的方法,如下代码所示:

  1. import Qt 4.7
  2. import Shapes 5.0   //自定义模块
  3. Item {
  4. width: 300; height: 200
  5. Ellipse {
  6. x: 50; y: 35; width: 200; height: 100
  7. color: "blue"
  8. MouseArea {
  9. anchors.fill: parent
  10. // 调用C++中定义的randomColor方法
  11. onClicked: parent.color = parent.randomColor()
  12. }
  13. }
  14. }

为了让上述QML代码成功的调用下面这段代码定义的randomColor()函数,最为关键的一点见randomColor方法用Q_INVOKABLE 修饰。

  1. #include <QDeclarativeItem >
  2. class EllipseItem : public QDeclarativeItem
  3. {
  4. Q_OBJECT
  5. public:
  6. Q_INVOKABLE QColor randomColor() const;

更多细节,请参看我的另一篇博文:QML与C++混合编程使用

在跨线程编程中的使用

我们如何调用驻足在其他线程里的QObject方法呢?Qt提供了一种非常友好而且干净的解决方案:向事件队列post一个事件,事件的处理将以调用我们所感兴趣的方法为主(当然这需要线程有一个正在运行的事件循环)。而触发机制的实现是由moc提供的内省方法实现的。因此,只有信号、槽以及被标记成Q_INVOKABLE的方法才能够被其它线程所触发调用。如果你不想通过跨线程的信号、槽这一方法来实现调用驻足在其他线程里的QObject方法。另一选择就是将方法声明为Q_INVOKABLE,并且在另一线程中用invokeMethod唤起。

更多细节,译文事件循环与线程

Qt Service Framework

Qt服务框架是Qt Mobility 1.0.2版本推出的,一个服务(service)是一个独立的组件提供给客户端(client)定义好的操作。客户端可以通过服务的名称,版本号和服务的对象提供的接口来查找服务。 查找到服务后,框架启动服务并返回一个指针。

服务通过插件(plug-ins)来实现。为了避免客户端依赖某个具体的库,服务必须继承自QObject。这样QMetaObject系统可以用来提供动态发现和唤醒服务的能力。要使QmetaObject机制充分的工作,服务必须满足,其所有的方法都是通过 signal,slot,property 或invokable methodQ_INVOKEBLE来实现

其中,最常见的与servicer交互的方法如下:

  1. QServiceManager manager;QObject *storage ;
  2. storage = manager.loadInterface("com.nokia.qt.examples.FileStorage"); if (storage)     QMetaObject::invokeMethod(storage, "deleteFile", Q_ARG(QString, "/tmp/readme.txt"));
上面的代码通过service的元对象提供的invokeMethod方法,调用文件存储对象的deleteFile() 方法。客户端不需要知道对象的类型,因此也没有链接到具体的service库。  当然在服务端的deleteFile方法,一定要被标记为Q_INVOKEBLE,才能够被元对象系统识别

Qt服务框架的一个亮点是它支持跨进程通信,服务可以接受远程进程。在服务管理器上注册后 进程通过signal,slot,invokable method和property来通信,就像本地对象一样。服务可以设定为在客户端间共享,或针对一个客户端。  请注意,在Qt服务框架推出之前,信号、槽以及invokable method仅支持跨线程。 下图是跨进成的服务/客户段通信示意图(图片来自诺基亚论坛)。这里我们可以清楚的看到,invokable methodQ_INVOKEBLE 是跨进城、跨线程对象之间通信的重要利器。

Q_INVOKABLE与invokeMethod用法全解的更多相关文章

  1. CSS样式设置语法全解,样式优先级、值和单位、字体、文本、块级元素,行内元素,替换元素、非替换元素、display、float、position、table、li、光标、边距边框、轮廓、颜色背景

    全栈工程师开发手册 (作者:栾鹏) 一个demo学会css css选择器全解 css操作语法全解 CSS样式设置语法全解: 样式优先级 1. !important标记的样式 > 内联样式(sty ...

  2. 解析Qt元对象系统(五) Q_INVOKABLE与invokeMethod(automatic connection从Qt4.8开始的解释已经与之前不同,发送对象驻足于哪一个线程并不重要,起到决定作用的是接收者对象所驻足的线程以及发射信号(该信号与接受者连接)的线程是不是在同一个线程)good

    概述查看Qt源码可知,Q_INVOKABLE是个空宏,目的在于让moc识别. 使用Q_INVOKABLE来修饰成员函数,目的在于被修饰的成员函数能够被元对象系统所唤起. Q_INVOKABLE与QMe ...

  3. laravel操作Redis排序/删除/列表/随机/Hash/集合等方法全解

    Song • 3563 次浏览 • 0 个回复 • 2017年10月简介 Redis模块负责与Redis数据库交互,并提供Redis的相关API支持: Redis模块提供redis与redis.con ...

  4. TSQL Identity 用法全解

    Identity是标识值,在SQL Server中,有ID列,ID属性,ID值,ID列的值等术语. Identity属性是指在创建Table时,为列指定的Identity属性,其语法是:column_ ...

  5. php利用ob缓存机制实现页面静态化方法全解

    首先介绍一下php中ob缓存常用到的几个常用函数 ob_start():开启缓存机制 ob_get_contents():获取ob缓存中的内容 ob_clean()清除ob缓存中的内容,但不关闭缓存 ...

  6. Java main方法全解

    1.main方法的重载 package cn.nxl2018; public class Main_test { public static void main(String args[]) { Sy ...

  7. binary 和 varbinary 用法全解

    在SQL Server中,使用数据类型 binary(n) 和 varbinary(n) 存储二进制数据,n是指字节数量: binary(n):固定长度为 n 字节,其中 n 值从 1 到 8,000 ...

  8. Join 和 Apply 用法全解

    在关系型数据库系统中,为了满足第三范式(3NF),需要将满足“传递依赖”的表分离成单独的表,通过Join 子句将相关表进行连接,Join子句共有三种类型:外连接,内连接,交叉连接:外连接分为:left ...

  9. Lookup 组件用法全解

    Lookup是查找的意思,Lookup组件实现两个数据源的连接,和Join语句实现的功能类似,使用Lookup 组件需要配置: 两个输入:一个是上游数据流的输入Source Table,一个是要查找的 ...

随机推荐

  1. HBase应用场景

    适用场景 列族结构经常调整 高并发写入 结构化数据及半结构化数据 Key-Value存储 有序存储 固定集合(多版本) 定时删除记录(TTL)   不适用场景 事务 join,union,groupb ...

  2. brew 更新

    更新: brew update brew update —system 安装, 如:brew install unrar 卸载, 如:brew uninstall unrar

  3. cocos2dx移植android平台-我的血泪史

    版权声明:本文由( 小塔 )原创,转载请保留文章出处! 本文链接:http://www.zaojiahua.com/android-platform.html 本人这几天一直都没有跟新自己的网站内容, ...

  4. linux top命令VIRT,RES,SHR,DATA的含义

    VIRT:virtual memory usage 虚拟内存1.进程“需要的”虚拟内存大小,包括进程使用的库.代码.数据等2.假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而 ...

  5. feof使用注意

    [feof使用注意] 以下是错误的用法,發生狀況->多讀一次?: FILE* pf; while(!feof(pf)){ //fread 讀取 //資料處理 } feof是發生在fread使用" ...

  6. Prefabs

    [Prefabs] A Prefab is a type of asset -- a reusable GameObject stored in Project View. Prefabs can b ...

  7. hdu 2444 The Accomodation of Students(最大匹配 + 二分图判断)

    http://acm.hdu.edu.cn/showproblem.php?pid=2444 The Accomodation of Students Time Limit:1000MS     Me ...

  8. C# 消息处理机制及自定义过滤方式

    一.消息概述 Windows 下应用程序的执行是通过消息驱动的.消息是整个应用程序的工作引擎,我们需要理解掌握我们使用的编程语言是如何封装消息的原理. 1. 什么是消息(Message) 消息就是通知 ...

  9. HTML5中script的async属性异步加载JS

    HTML5中script的async属性异步加载JS     HTML4.01为script标签定义了5个属性: charset 可选.指定src引入代码的字符集,大多数浏览器忽略该值.defer 可 ...

  10. UI:MVC设计模式

    不是因为有些事情难以做到,我们才失去自信:而是因为我们失去了自信,有些事情才显得难以做到.自信的第一步就是去尝试.不是因为有希望才坚持,而是因为坚持才有了希望.坚持尝试,就有可能成功.加油! Xcod ...