关闭

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

标签: bindingqtinterfacesignalobjectstring
2666人阅读 评论(0) 收藏 举报
分类:

对该问题的兴趣,源于之前的一个麻烦问题,如何让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消息返回。

 

 

 

 

 

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:172620次
    • 积分:2153
    • 等级:
    • 排名:第18254名
    • 原创:46篇
    • 转载:6篇
    • 译文:0篇
    • 评论:36条
    文章分类
    最新评论