追求
偶然在一个别的源码看到一个更方便的写法。
总体来说就一个xml和一些类型配置就解决了所有的问题,关键是这种方法是真的很方便简洁,如果以后需要调用别的dbus也可以模仿一下。
先总结一下主要的流程:
- xml 中写好标准的dbus接口写法,感觉是官方给出来的,但又找不到哈哈哈。好吧就算官方找不到自己写也行,就是有点多;
- cmake中可以通过QT5_ADD_DBUS_INTERFACE宏把xml自动生成cpp和h文件,主要提供了总线的方法接口;
- 新建cpp和h文件处理一些复合类型数据,合入到生成的总线接口类中;
生成的接口类
有了xml后,在CMakeList.txt中加入:
QT5_ADD_DBUS_INTERFACE(DBUS_INTERFACE_SRCS
org.freedesktop.login1.Manager.xml
login1_manager
)
命名为DBUS_INTERFACE_SRCS了,在add_executable后面添加此源add_executable(${PROJECT_NAME} “main.cpp” xxx… ${DBUS_INTERFACE_SRCS} )
在cmake的build目录里,会生成名为login1_manager.cpp和头文件,名字也是自己定的。
查看生成的login1_manager.h,它生成了一个OrgFreedesktopLogin1ManagerInterface类,继承QDBusAbstractInterface,就是qdbus类相关的操作,而后面的接口类似
...
inline QDBusPendingReply<InhibitorList> ListInhibitors()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ListInhibitors"), argumentList);
}
inline QDBusPendingReply<NamedSeatPathList> ListSeats()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ListSeats"), argumentList);
}
inline QDBusPendingReply<SessionInfoList> ListSessions()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ListSessions"), argumentList);
}
inline QDBusPendingReply<UserInfoList> ListUsers()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ListUsers"), argumentList);
}
inline QDBusPendingReply<> LockSession(const QString &in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return asyncCallWithArgumentList(QStringLiteral("LockSession"), argumentList);
}
...
全都是自动生成!
后面可以使用此类直接调用需要的方法了。
类型处理
在上一节中有提到,就是元数据声明定义之类的,把它同一放起来就行。
在CMakeList.txt中添加
set_source_files_properties("${CMAKE_SOURCE_DIR}/org.freedesktop.login1.Manager.xml" PROPERTIES
INCLUDE "LogindDBusTypes.h"
)
使它包含这个类型头文件,在这类型头文件里进行元数据声明,流操作定义,元数据注册操作即可。
感觉也是官方给的,就是找不到官方的地址了,这些看起来格式都一样,改也很容易改
由于生成的接口类头文件login1_manager.h是在cmake构建工程目录上面的,所以它会找不到处在源文件目录上的LogindDBusTypes.h,这时只需要拷贝这个头文件过去即可:
configure_file("LogindDBusTypes.h" "${CMAKE_BINARY_DIR}/LogindDBusTypes.h" COPYONLY)
用起来!
用就更简单了,直接疯狂调用接口即可:
if (Logind::isAvailable()) {
OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus());
auto reply = manager.ListSessions();
reply.waitForFinished();
for (int i = 0; i < reply.value().count(); i++){
qCritical() << reply.value().at(i).userName;
}
}