您的位置:首页 > 编程语言 > Qt开发

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

2011-01-19 18:17 609 查看
对该问题的兴趣,源于之前的一个麻烦问题,如何让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消息返回。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: