QDBus使用
一.服务端
1.需要导出的类继承QObject,将需要导出的接口放在public slots中。
2.定义接口:Q_CLASSINFO("D-Bus Interface", "com.XXX.XXX.XX.Interface")
3.生成XML接口文件
Qdbuscpp2xml -M XXX.h -o com.xx.xxx.xml
将类中导出的接口生成xml文件格式
4.生成Adaptor文件
Qdbusxml2cpp com.xx.xxx.xml -i XXX.h -a XXXAdaptor
5.生成Interface文件供客户端调用
Qdbusxml2cpp com.xx.xxx.xml -i XXX.h -p XXXInterface
6.代码
QDBusConnection drPointDBus = QDBusConnection::sessionBus();
CXXX* xxx = new CXXX(0);
InterfaceAdaptor* drAdaptor = new InterfaceAdaptor(xxx );
bool dbusRegRet = drPointDBus.registerService(NAVI_XXX_SERVICE);
if(dbusRegRet == false)
{
qDebug("Register QDBus Service Error!");
return 0;
}
dbusRegRet = drPointDBus.registerObject(NAVI_XXX_PATH, xxx , QDBusConnection::ExportAllContents);
if(dbusRegRet == false)
{
qDebug("Register QDBus Object Error!");
return 0;
}
二.客户端
1.客户端连接QDBus
com::XXX::XXX::XX::Interface *m_pXXXXInface =
new ComXXXInterfaceInterface(NAVI_XXX_SERVICE, NAVI_XXX_PATH,QDBusConnection::sessionBus());
2.调用接口
QDBusPendingReply<XXX> posReply = m_pXXXXInface->XXXXXX();
posReply.waitForFinished();
posReply.isValid()
3.客户端使用服务端提使用XML生成的Interface文件调用接口
三.服务端导出结构体的情况
1.定义结构体
struct SPositionInfo
{
int mode; // DR定位状态 0:未定位,1:2D定位,2:3D定位
double latitude; // 纬度
double longitude; // 经度
int speed; // 速度 单位 1cm/s
friend QDBusArgument&operator <<(QDBusArgument&argument, const SPositionInfo&arg)
{
argument.beginStructure();
argument << arg.mode;
argument << arg.latitude;
argument << arg.longitude;
argument << arg.speed;
argument.endStructure();
return argument;
}
friend const QDBusArgument &operator >>(const QDBusArgument&argument, SPositionInfo&arg)
{
argument.beginStructure();
argument >> arg.mode;
argument >> arg.latitude;
argument >> arg.longitude;
argument >> arg.speed;
argument.endStructure();
return argument;
}
};
Q_DECLARE_METATYPE(SPositionInfo)
2.注册
服务端和客户端需要注册结构体
qRegisterMetaType<SPositionInfo>("SPositionInfo");
qDBusRegisterMetaType<SPositionInfo>();
3.如果结构体中含有结构体数组,结构体数组有数量限制
4.XML中结构体中数据类型定义
a ARRAY 数组
b BOOLEAN 布尔值
d DOUBLE IEEE 754双精度浮点数
g SIGNATURE 类型签名
i INT32 32位有符号整数
n INT16 16位有符号整数
o OBJECT_PATH 对象路径
q UINT16 16位无符号整数
s STRING 零结尾的UTF-8字符串
t UINT64 64位无符号整数
u UINT32 32位无符号整数
v VARIANT 可以放任意数据类型的容器,数据中包含类型信息。例如glib中的GValue。
x INT64 64位有符号整数
y BYTE 8位无符号整数
() 定义结构时使用。例如"(i(ii))"
{} 定义键-值对时使用。例如"a{us}"
5.定义结构体需要在XML中声明
<annotation value="SPositionInfo" name="org.qtproject.QtDBus.QtTypeName.Out0"/>
四.服务端发送消息
1.服务端
1.1使用signal发送消息emit,只能在导出接口的类中使用
1.2使用QDBusMessage发送消息,可以在类中任意地方使用
QDBusMessage msg = QDBusMessage::createSignal("/gps/register", "com.XXX.XXX.Interface", "GetNXXXSignal");
QDBusConnection::sessionBus().send(msg);
1.3检查消息是否发送到dbus
D-feet工具,在终端使用命令dbus-monitor --session \ "type='signal'"可以查看dubs接收的信号。
2.客户端
使用类中槽函数接收消息
QDBusConnection::sessionBus().connect(NAVI_XXX.XXX_SERVICE, NAVI_XXX.XXX_PATH, "com.XXX.XXX.XX.Interface", "GetXXXSignal",
this, SLOT(getData()));
五.使用SystemBus
如果使用系统bus需要在目录下创建对应服务器的配置文件
/etc/dbus-1/system.d/org.XXX.XX.conf
内容类似:
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="root">
<allow own="org.xx.xx"/>
<allow send_destination="org.xx.xx"/>
<allow send_interface="org.xx.xx"/>
</policy>
<policy at_console="true">
<allow send_destination="org.xx.xx"/>
<allow send_interface="org.xx.xx"/>
</policy>
<policy context="default">
<deny own="org.xx.xx"/>
<deny send_destination="org.xx.xx"/>
<deny send_interface="org.xx.xx"/>
</policy>
</busconfig>