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.
-
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.
-
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.