通过 dbus 共享对象
Posted
技术标签:
【中文标题】通过 dbus 共享对象【英文标题】:Sharing objects over dbus 【发布时间】:2015-11-14 13:33:02 【问题描述】:我的项目来源于这个例子:http://doc.qt.io/qt-5/qtdbus-remotecontrolledshower-example.html
有两个进程,淋浴器和控制器,控制器可以向淋浴器发送简单的消息(我只是将那个项目中的汽车重命名为淋浴器)并将花哨的汽车 GUI 更改为一个简单的 Widget。我这样做没有任何问题。 我的问题是当我尝试使用自定义类发送消息时
#ifndef MESSAGE_H
#define MESSAGE_H
#include <QtDBus>
class message
public:
QString articleName;
QString categoryName;
message() : articleName(""), categoryName("")
message( QString a, QString b ) : articleName(a), categoryName(b)
message(const message &other) : articleName( other.articleName ), categoryName( other.categoryName )
message& operator=(const message &other)
articleName = other.articleName;
categoryName = other.categoryName;
return *this;
//register Message with the Qt type system
static void registerMetaType()
qRegisterMetaType<message>("message");
qDBusRegisterMetaType<message>();
friend QDBusArgument &operator<<(QDBusArgument &argument, const message &mess )
argument.beginStructure();
argument << mess.articleName;
argument << mess.categoryName;
argument.endStructure();
return argument;
friend const QDBusArgument &operator>>(const QDBusArgument &argument, message &mess )
argument.beginStructure();
argument >> mess.articleName;
argument >> mess.categoryName;
argument.endStructure();
return argument;
;
Q_DECLARE_METATYPE( message )
#endif // MESSAGE_H
我在接收消息对象的淋浴类中添加了一个方法
#ifndef shower_H
#define shower_H
#include "ui_Categories.h"
#include "message.h"
class shower : public QWidget
Q_OBJECT
public:
shower(QWidget *parent = 0);
//shower();
//QRectF boundingRect() const;
public Q_SLOTS:
void accelerate();
void decelerate();
void turnLeft();
void turnRight();
void doThat();
void addMessage( const message &msg );
QString Get( int param );
Q_SIGNALS:
void crashed();
protected:
void timerEvent(QTimerEvent *event);
private:
Ui::Categories ui;
qreal wheelsAngle; // used when applying rotation
qreal speed; // delta movement along the body axis
;
#endif // shower_H
这是我定义淋浴界面的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/shower">
<interface name="org.example.Examples.showerInterface">
<method name="accelerate"/>
<method name="decelerate"/>
<method name="turnLeft"/>
<method name="turnRight"/>
<method name="addMessage">
<arg name="param" type="a(ii)" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="message"/>
</method>
<signal name="crashed"/>
</interface>
</node>
还有专业文件
QT += dbus widgets
DBUS_ADAPTORS += shower.xml
HEADERS += shower.h \
message.h
SOURCES += shower.cpp main.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/dbus/wikidbusqt/shower
INSTALLS += target
FORMS += \
Categories.ui
OTHER_FILES += \
shower.xml
我无法编译,我得到了这个错误日志
20:45:21: Running steps for project wikidbusqt...
20:45:21: Starting: "/usr/lib/x86_64-linux-gnu/qt5/bin/qmake" /home/hector/workspace/wikidbusqt/shower/shower.pro -r -spec linux-g++-64
20:45:21: The process "/usr/lib/x86_64-linux-gnu/qt5/bin/qmake" exited normally.
20:45:21: Starting: "/usr/bin/make"
/usr/lib/x86_64-linux-gnu/qt5/bin/uic ../../wikidbusqt/shower/Categories.ui -o ui_Categories.h
g++ -c -m64 -pipe -O2 -Wall -W -D_REENTRANT -fPIE -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_DBUS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++-64 -I../../wikidbusqt/shower -I/usr/include/qt5 -I/usr/include/qt5/QtWidgets -I/usr/include/qt5/QtDBus -I/usr/include/qt5/QtGui -I/usr/include/qt5/QtCore -I. -I. -I. -o shower.o ../../wikidbusqt/shower/shower.cpp
In file included from /usr/include/qt5/QtCore/qvariant.h:48:0,
from /usr/include/qt5/QtCore/QVariant:1,
from ./ui_Categories.h:12,
from ../../wikidbusqt/shower/shower.h:46,
from ../../wikidbusqt/shower/shower.cpp:42:
/usr/include/qt5/QtCore/qmetatype.h:1708:12: error: specialization of 'QMetaTypeId<message>' after instantiation
struct QMetaTypeId< TYPE > \
^
../../wikidbusqt/shower/message.h:53:1: note: in expansion of macro 'Q_DECLARE_METATYPE'
Q_DECLARE_METATYPE( message )
^
/usr/include/qt5/QtCore/qmetatype.h:1708:12: error: redefinition of 'struct QMetaTypeId<message>'
struct QMetaTypeId< TYPE > \
^
../../wikidbusqt/shower/message.h:53:1: note: in expansion of macro 'Q_DECLARE_METATYPE'
Q_DECLARE_METATYPE( message )
^
/usr/include/qt5/QtCore/qmetatype.h:1491:8: error: previous definition of 'struct QMetaTypeId<message>'
struct QMetaTypeId : public QMetaTypeIdQObject<T>
^
In file included from /usr/include/qt5/QtCore/qatomic.h:42:0,
from /usr/include/qt5/QtCore/qvariant.h:45,
from /usr/include/qt5/QtCore/QVariant:1,
from ./ui_Categories.h:12,
from ../../wikidbusqt/shower/shower.h:46,
from ../../wikidbusqt/shower/shower.cpp:42:
/usr/include/qt5/QtCore/qmetatype.h: In instantiation of 'int qMetaTypeId() [with T = message]':
/usr/include/qt5/QtDBus/qdbusmetatype.h:85:29: required from 'int qDBusRegisterMetaType(T*) [with T = message]'
../../wikidbusqt/shower/message.h:28:40: required from here
/usr/include/qt5/QtCore/qglobal.h:679:85: error: invalid application of 'sizeof' to incomplete type 'QStaticAssertFailure<false>'
enum Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __COUNTER__) = sizeof(QStaticAssertFailure<!!(Condition)>)
^
/usr/include/qt5/QtCore/qglobal.h:684:47: note: in expansion of macro 'Q_STATIC_ASSERT'
#define Q_STATIC_ASSERT_X(Condition, Message) Q_STATIC_ASSERT(Condition)
^
/usr/include/qt5/QtCore/qmetatype.h:1638:5: note: in expansion of macro 'Q_STATIC_ASSERT_X'
Q_STATIC_ASSERT_X(QMetaTypeId2<T>::Defined, "Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system");
^
make: *** [shower.o] Error 1
20:45:24: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project wikidbusqt (kit: Desktop)
When executing step 'Make'
20:45:24: Elapsed time: 00:03.
我不知道发生了什么,我按照本教程中概述的步骤操作:https://techbase.kde.org/Development/Tutorials/D-Bus/CustomTypes#DBusChat.pro,但我不知道我忽略了什么。
【问题讨论】:
【参考方案1】:您只能在Q_DECLARE_METATYPE
在范围内之后调用qRegisterMetaType
和类似方法。因此,您必须将registerMetaType()
的主体移出类,放入.cpp
文件中:
message.h(相关片段)
...
class message
...
/// Register message with the Qt type system.
static void registerMetaType();
...
;
Q_DECLARE_METATYPE( message )
...
message.cpp(整个文件)
#include "message.h"
void message::registerMetaType()
qRegisterMetaType<message>("message");
qDBusRegisterMetaType<message>();
您不能将registerMetaType
的类外定义放入头文件,因为它会破坏单一定义规则并且链接器会抱怨多重定义的符号。
【讨论】:
谢谢!现在看来,我的 IDE 正在做一些奇怪的事情:它生成了一个 Makefile,它不会将 message.h 添加到 qdbusxml2cpp 调用中。在使用 qmake 生成的 makefile 中,我得到shower_adaptor.h: ../../wikidbusqt/shower/shower.xml /usr/lib/x86_64-linux-gnu/qt5/bin/qdbusxml2cpp -a shower_adaptor.h: ../../wikidbusqt/shower/shower.xml
并且无法编译当它应该是 shower_adaptor.h: ../../wikidbusqt/shower/shower.xml /usr/lib/x86_64-linux-gnu/qt5/bin/qdbusxml2cpp -i message.h -a shower_adaptor.h: ../../wikidbusqt/shower/shower.xml
这编译时以上是关于通过 dbus 共享对象的主要内容,如果未能解决你的问题,请参考以下文章