Qt & DBus problem with slot/method not working
-
I've been making myself a small DBus testing program for Qt, and have run into a problem, where after scouring the web for a few hours I'm still stumped.
My object has a public property and public slot. When I run my program, also while using 'qdbusviewer', I see the property and the slot/method, but as soon as I try to call the method (with the qdbusviewer dialog) it says method not found. The test is quite short, so I'll post the whole thing.
main.cpp
@#include <iostream>#include <QCoreApplication>
#include "dbusobject.h"
int main( int argc, char **argv )
{
std::cout << "Welcome to DBusObject test" << std::endl;QCoreApplication app(argc,argv); DBusObject obj; return app.exec();
}
@
dbusobject.h
@#ifndef DBUSOBJECT_H
#define DBUSOBJECT_H#include <QObject>
class DBusObject : public QObject
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "com.foo.bar.DBusObject")
Q_PROPERTY(uint globs READ globs)public:
DBusObject(QObject* parent=0);uint globs() const;
public slots:
void setGlobs(const uint);private:
int numGlobs;
};#endif
@dbusobject.cpp
@
#include <iostream>#include <QDBusConnection>
#include "dbusobject.h"
#include "dbusobjectadaptor.h"DBusObject::DBusObject(QObject* parent) :
QObject(parent)
{
numGlobs = 0;new DBusObjectAdaptor(this); QDBusConnection connection = QDBusConnection::sessionBus(); connection.registerObject("/DBusObject", this); connection.registerService("com.foo.bar.DBusObject");
}
uint DBusObject::globs() const
{
std::cout << " # of globs=" << numGlobs << std::endl;
return numGlobs;
}void DBusObject::setGlobs(const uint g)
{
std::cout << " setting globs=" << g << std::endl;
numGlobs = g;
}@
Using the following commands, I make the adaptor.
qdbuscpp2xml -M -P dbusobject.h -o com.foo.bar.DBusObject.xml
qdbusxml2cpp -c DBusObjectAdaptor -a dbusobjectadaptor.h:dbusobjectadaptor.cpp com.foo.bar.DBusObject.xmlcom.foo.bar.DBusObject.xml
@<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="com.foo.bar.DBusObject">
<property name="globs" type="u" access="read"/>
<method name="setGlobs">
<arg type="u" direction="in"/>
</method>
</interface>
</node>
@dbusobjectadaptor.h
@/*- This file was generated by qdbusxml2cpp version 0.7
- Command line was: qdbusxml2cpp -c DBusObjectAdaptor -a dbusobjectadaptor.h:dbusobjectadaptor.cpp com.foo.bar.DBusObject.xml
- qdbusxml2cpp is Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
- This is an auto-generated file.
- This file may have been hand-edited. Look for HAND-EDIT comments
- before re-generating it.
*/
#ifndef DBUSOBJECTADAPTOR_H_1345661941
#define DBUSOBJECTADAPTOR_H_1345661941#include <QtCore/QObject>
#include <QtDBus/QtDBus>
class QByteArray;
template<class T> class QList;
template<class Key, class Value> class QMap;
class QString;
class QStringList;
class QVariant;/*
- Adaptor class for interface com.foo.bar.DBusObject
*/
class DBusObjectAdaptor: public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "com.foo.bar.DBusObject")
Q_CLASSINFO("D-Bus Introspection", ""
" <interface name="com.foo.bar.DBusObject">\n"
" <property access="read" type="u" name="globs"/>\n"
" <method name="setGlobs">\n"
" <arg direction="in" type="u"/>\n"
" </method>\n"
" </interface>\n"
"")
public:
DBusObjectAdaptor(QObject *parent);
virtual ~DBusObjectAdaptor();
public: // PROPERTIES
Q_PROPERTY(uint globs READ globs)
uint globs() const;public Q_SLOTS: // METHODS
void setGlobs(uint in0);
Q_SIGNALS: // SIGNALS
};#endif
@dbusobjectadaptor.cpp
@/*- This file was generated by qdbusxml2cpp version 0.7
- Command line was: qdbusxml2cpp -c DBusObjectAdaptor -a dbusobjectadaptor.h:dbusobjectadaptor.cpp com.foo.bar.DBusObject.xml
- qdbusxml2cpp is Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
- This is an auto-generated file.
- Do not edit! All changes made to it will be lost.
*/
#include "dbusobjectadaptor.h"
#include <QtCore/QMetaObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>/*
- Implementation of adaptor class DBusObjectAdaptor
*/
DBusObjectAdaptor::DBusObjectAdaptor(QObject *parent)
: QDBusAbstractAdaptor(parent)
{
// constructor
setAutoRelaySignals(true);
}DBusObjectAdaptor::~DBusObjectAdaptor()
{
// destructor
}uint DBusObjectAdaptor::globs() const
{
// get the value of property globs
return qvariant_cast< uint >(parent()->property("globs"));
}void DBusObjectAdaptor::setGlobs(uint in0)
{
// handle method call com.foo.bar.DBusObject.setGlobs
QMetaObject::invokeMethod(parent(), "setGlobs", Q_ARG(uint, in0));
}@
The entire thing compiles and runs fine, and I can access the property and get a result. When I try to call the setGlobs method I get:
Unable to find method setGlobs on path /DBusObject in interface com.foo.bar.DBusObject
What am I missing here?
-
A quick addendum:
If I reload 'qdbusviewer' while qbustest is running, I can invoke the method without the error shown above, but nothing ever happens. The adaptor method 'void DBusObjectAdaptor::setGlobs(uint in0)' doesn't get called, nor the slot in my object.
-
Well, maybe slot is called, but invokeMethod does not work. At least I already experience such kind of problems. You can check if your adapter receives call of slot with some debug like
@
#include <QDebug>void DBusObjectAdaptor::setGlobs(uint in0)
{
// handle method call com.foo.bar.DBusObject.setGlobsqDebug() << "Hello I am in adaptor"; QMetaObject::invokeMethod(parent(), "setGlobs", Q_ARG(uint, in0));
}
@On the other hand you can change invoke to direct call of slot
@
static_cast<DBusObject *>(paretent())->setGlobs(in0));
@Let me know if that solved your problem.
-
@void DBusObjectAdaptor::setGlobs(uint in0)@
does not get called when I use the dialog in 'qdbusviewer'.
So I assume trying to change the internals of it wont work
-
qdbusviewer shows property and method:
Invoking method, with the unsigned in 123.
!https://lh6.googleusercontent.com/-j0duxRX92_c/UDVJd6GAeII/AAAAAAAAAD4/ZXSryD2wWcY/s413/qdbus2.png(Using method dialog)!
Clicking OK does nothing.
-
You could give a try to my proposition of adding debug, cout or any other text message in adaptor. The method can be called correctly but call of method with realize this interface could fails.
-
In addition, you could also try another DBus tools to check calling of method, for instance
d-feet
dbus-monitor
Maybe they will give you more information about problem.
-
I used dbus-monitor (new to dbus, wasnt aware of its existence) And found the problem.
dbus-monitor
method call sender=:1.256 -> dest=com.foo.bar.DBusObject serial=31 path=/DBusObject; interface=com.foo.bar.DBusObject; member=setGlobs
int32 123
error_name=org.freedesktop.DBus.Error.UnknownMethod reply_serial=31
string "No such method 'setGlobs' in interface 'com.foo.bar.DBusObject' at object path '/DBusObject' (signature 'i')"Even though, as seen in the image above, qdbusviewer shows it is taking a uint argument, it apparently is trying to send that argument as a signed int to the method, which fails.
I created my own tester program which uses a uint, and the program works as it should.