QT 4.7 DBUS Binding如何支持自定义数据类型的传输(一)

原创 2011年01月19日 18:17:00

对该问题的兴趣,源于之前的一个麻烦问题,如何让QT 4.7 支持DBUS调用中传递"aas(字符串二维数组)“ 数据据类型(详见http://blog.csdn.net/shallon_luo/archive/2011/01/18/6149616.aspx),虽然该问题已经解决,但是只能算了解个配置方法,下面是更深入的了解。

 

首先是找了一个更深入的学习资料http://laurii.info/articles/2007/03/22/dbus-and-qt-programming 下文的学习资料的代码例子从该链接可以下载。

 

这里先讨论,QT DBUS Binding用在通信的服务器端的情形。

 

第一步,首先看看这个示例DBUS接口的描述XML

 

<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
        "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/com/trollech/examples/car">
        <interface name="com.trolltech.Examples.CarInterface">
                <method name="accelerate"/>
                <method name="decelerate"/>
                <method name="turnLeft"/>
                <method name="turnRight"/>
                <method name="structer">
                    <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MyStruct"/>
                    <arg type="(sxs)" direction="out"/>
                    <arg type="x" direction="out"/>
                </method>
                <signal name="crashed"/>
        </interface>
</node>

可以注意到:1.这个红色字体函数声明中,有两个返回参数。 2.第一个返回参数被声明成了自定义的类型MyStruct .

 

第二步,看看QT DBUS Binding工具 qdbusxml2cpp是怎么翻译这个XML文件

 

运行 qdbusxml2cpp -i mystruct.h -c CarAdaptor -a car_adaptor_p.h:car_adaptor.cpp car.xml

 

注意,这是服务器端运行的命令,客户端运行另一命令(qdbusxml2cpp -c CarInterface -p car_interface_p.h:car_interface.cpp  -i mystruct.h  car.xml) 这里不再描述。

 

第三步,看看生成的car_adaptor_p.h:car_adaptor.cpp文件,能发现下列问题

1. 生成了CarAdaptor,该类是QDBusAbstractAdaptor的一个子类。QDBusAbstractAdaptor是QT对象与DBUS绑定的桥梁。其基本用法是:

a: QDBusAbstractAdaptor其子类是一个普通 QObject对象的轻量封装对象,在此处QObject对象是提供DBUS服务的业务对象。在代码中,这个QObject对象称为“QDBusAbstractAdaptor的parent对象” ,在本例子中,这个业务对象是Car对象。

 

b:通过QDBusConnection::registerObject方法注册parent对象。(见第四步的main函数的逻辑部分)

 

2.CarAdaptor通过Q_CLASSINFO将DBUS访问的接口信息插入QT元数据描述中。

 

    Q_OBJECT
    Q_CLASSINFO("D-Bus Interface", "com.trolltech.Examples.CarInterface")
    Q_CLASSINFO("D-Bus Introspection", ""
"  <interface name=/"com.trolltech.Examples.CarInterface/" >/n"
"    <method name=/"accelerate/" />/n"
"    <method name=/"decelerate/" />/n"
"    <method name=/"turnLeft/" />/n"
"    <method name=/"turnRight/" />/n"
"    <method name=/"structer/" >/n"
"      <annotation value=/"MyStruct/" name=/"com.trolltech.QtDBus.QtTypeName.Out0/" />/n"
"      <arg direction=/"out/" type=/"(sxs)/" />/n"
"      <arg direction=/"out/" type=/"x/" />/n"
"    </method>/n"
"    <signal name=/"crashed/" />/n"
"  </interface>/n"
        "")

这里很难能透彻理解,可以运行qmake ,看看其生成的moc_car_adaptor_p.cpp文件,看看Q_CLASSINFO插入DBUS值对真正的代码是什么。

 

3.发现XML定义的structer函数原型被映射成:

 

public Q_SLOTS:
MyStruct structer(qlonglong &out1);

 

其规律是第一个返回的参数被定义成返回值,第二个返回的参数被映射成引用的参数。

 

第四步,看看MyStruct 的自定义

 

class MyStruct {
public:
        QString element1;
        qlonglong element2;
        QString element3;
};

Q_DECLARE_METATYPE(MyStruct)


inline void registerCommTypes() {
        qDBusRegisterMetaType<MyStruct>();
}

QDBusArgument &operator<<(QDBusArgument &argument, const MyStruct &mystruct);
const QDBusArgument &operator>>(const QDBusArgument &argument,
        MyStruct &mystruct);

 

1.定义MyStruct 的结构

2.声明MyStruct的元数据类型

3.向QT Dbus Binding注册MyStruct元数据类型

4.实现序列化与反序列化的函数 << | >> 用于从DBUS文本消息到MyStruct的双向转换。

 

5.Main 函数,主要逻辑如下:

 

    new CarAdaptor(car);
    QDBusConnection connection = QDBusConnection::sessionBus();
    connection.registerObject("/Car", car);
    connection.registerService("com.trolltech.CarExample");

 

6.调用流程日志

1.DBUS消息如下:

 

method call sender=:1.386 -> dest=:1.384 serial=166 path=/Car; interface=com.trolltech.Examples.CarInterface; member=structer
method return sender=:1.384 -> dest=:1.386 reply_serial=166
   struct {
      string "unu"
      int64 2
      string "trei"
   }
   int64 12345

 

2.程序调用日志显示调用路径

 

QDBusArgument &operator<<(mystruct.cpp)
 
Calling structer (carAdaptor.cpp)
Calling structer (car.cpp)
QDBusArgument &operator<<(mystruct.cpp)

从日志可以分析,第一条DBUS消息发出后,首先进入的是carAdaptor.cpp的structer函数,然后进入其业务对象Car的structer函数。最后运行结果返回,structer返回的MyStrct对象是序列化成DBUS消息被发送给客户端。

 

这里不解的地方是:为何QDBusArgument &operator<<被调用了两次?

 

分析:

 

当DBUS请求发送过来时,QT DBUS Binding应该是通过carAdaptor.cpp注册的DBUS 元数据信息找到了CarAdaptor对象,并且触发相关的方法,CarAdaptor对象将请求转发给其parent对象(Car),运行完成后由QT DBUS框架自动进行序列化成DBUS消息返回。

 

 

 

 

 

 

相关文章推荐

QT中DBus的用法

 目  录1 概述... 22 QT中Dbus的最简单的用法... 33 QT中DBus的常规用法... 43.1 客户端的用法1:使用QDBusMessage. 43.2客户端的用法2:使用DBus...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Qt浅谈之二十七进程间通信之QtDBus

原文地址::http://blog.csdn.net/taiyang1987912/article/details/45642079 相关文章 1、QT中DBus的用法----http://blo...

使用qt dbus 传递复杂数据结构的方法

参考文章http://blog.csdn.net/cuijpus/article/details/2295306   如何用dbus-glib传递复杂的数据结构     经过多次试验 qdbusxm...
  • l_yy_l
  • l_yy_l
  • 2011年10月27日 10:31
  • 1006

Qt中菜单创建及自定义数据类型与QVariant互转

diagramtextitem.h: /**************************************************************************** ** ...

MapReduce模型--自定义数据类型

  • 2013年05月28日 15:40
  • 81KB
  • 下载

如何在Qt中使用自定义数据类型

本文转载至: http://blog.163.com/jx_yp/blog/static/1197044592011119105843436/ 这里我们使用下面这个struct来做说明(这里...
  • plfl520
  • plfl520
  • 2012年08月07日 07:15
  • 518
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:QT 4.7 DBUS Binding如何支持自定义数据类型的传输(一)
举报原因:
原因补充:

(最多只允许输入30个字)