| Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date | |
| All threads index page 2 | |
Hello everybody
I have a question regarding the registration of signals and slots in a D-Bus
interface.
I have the following class (reduced to the minimum)
class RDLDExchangeServerDBus : public RDLDExchangeServerStrategy
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "rdld.provide.position")
public:
RDLDExchangeServerDBus (bool showPos)
public slots:
Q_SCRIPTABLE QString getTagList ();
Q_SCRIPTABLE QString getNodeList ();
Q_SCRIPTABLE QString getNodeInfo (int deviceId);
Q_SCRIPTABLE QString getPosition (int tagId);
Q_SCRIPTABLE QString getStrength (int tagId);
signals:
void updatedNode (int id, int x, int y, int z);
void updatedPosition (int tagId, int timestamp, double x, double y, double
z);
void updatedStrength (int id, int nodeId, int strength);
private:
QDBusConnection * dBus;
};
All Scriptable slots and all signals should be registered as D-Bus
Methods/signals. Except and that is the problem, if showPos is true than
getStrength and updatedStrength should not be registered, if it is false
getPosition and updatedPosition should not be registered.
The registration is done like this right now:
RDLDExchangeServerDBus::RDLDExchangeServerDBus (bool showPos)
{
dBus = new QDBusConnection ("");
dBus->connectToBus (QDBusConnection::ActivationBus, "");
if (!dBus->sessionBus().isConnected())
{
//print error
return ;
}
if (!dBus->sessionBus().registerService(""))
{
//print error
return ;
}
dBus->sessionBus().registerObject(QString ("/%1").arg(""), this,
QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportAllSignals);
}
is there a way to let dBus->sessionBus().registerObject () only register
specific methods and signals? or perhaps another method to do so?
Thanks in advance
Simon
--
[ signature omitted ]
On Tuesday 11 March 2008 15:17:38 Simon SchÃfer wrote: > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂQDBusConnection *ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂdBus; Suggestion: don't use a pointer here. Use a QDBusConnection object. You'll have to initialise it in your constructor, though. > }; > > All Scriptable slots and all signals should be registered as D-Bus > Methods/signals. Except and that is the problem, if showPos is true than > getStrength and updatedStrength should not be registered, if it is false > getPosition and updatedPosition should not be registered. That's not possible with the current API. Nor is there any plan to do so. > is there a way to let dBus->sessionBus().registerObject () only register > specific methods and signals? or perhaps another method to do so? No. I recommend instead that you use multiple interfaces. Create two Adaptor classes and instantiate the one you want to expose. -- [ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.
On Tuesday 11 March 2008 15:31:16 Thiago Macieira wrote:
first of all thanks for the fast answer.
> On Tuesday 11 March 2008 15:17:38 Simon Schäfer wrote:
> > QDBusConnection * dBus;
>
> Suggestion: don't use a pointer here. Use a QDBusConnection object.
>
> You'll have to initialise it in your constructor, though.
I tried different ways and all lead to strange compile errors, only the
pointer with creating a new object is working flawless.
The other two ways:
QDBus::sessionBus().... leads to:
rdldExchangeServerDBusPosition.cpp:55: error: 'sessionBus' is not a member
of 'QDBus'
and
using this in the header:
QDBusConnection dBus;
and changing all -> to . and delete the new leads to the following:
In
constructor 'RDLDExchangeServerDBusPosition::RDLDExchangeServerDBusPosition(RDLDLog*,
QString, QString)':
rdldExchangeServerDBusPosition.cpp:38: error: no matching function for call
to 'QDBusConnection::QDBusConnection()'
/usr/include/qt4/QtDBus/qdbusconnection.h:164: note: candidates are:
QDBusConnection::QDBusConnection(QDBusConnectionPrivate*)
/usr/include/qt4/QtDBus/qdbusconnection.h:114: note:
QDBusConnection::QDBusConnection(const QDBusConnection&)
/usr/include/qt4/QtDBus/qdbusconnection.h:113: note:
QDBusConnection::QDBusConnection(const QString&)
The following is the source at line 38:
37 RDLDExchangeServerDBusPosition::RDLDExchangeServerDBusPosition (RDLDLog *
pLog, QString connectionBasePath, QString subPath)
38 : RDLDExchangeServerDBusCommon (pLog, this)
39 {
So I still use the old way
>
> > is there a way to let dBus->sessionBus().registerObject () only register
> > specific methods and signals? or perhaps another method to do so?
>
> No. I recommend instead that you use multiple interfaces. Create two
> Adaptor classes and instantiate the one you want to expose.
I tried to implement the way you described but now I am getting a Segmentation
fault when I run my application. Backtrace:
#0 0x00002ac783121e28 in QObject::thread ()
from /usr/lib64/qt4/libQtCore.so.4
#1 0x00002ac78312301e in QObject::QObject ()
from /usr/lib64/qt4/libQtCore.so.4
#2 0x00002ac7837363b2 in QDBusAbstractAdaptor::QDBusAbstractAdaptor ()
from /usr/lib64/qt4/libQtDBus.so.4
#3 0x000000000040e767 in RDLDExchangeServerDBusCommon (this=0x641940,
pLog=0x641390, obj=0x641940) at rdldExchangeServerDBusCommon.cpp:36
#4 0x00000000004177ac in RDLDExchangeServerDBusPosition (this=0x641940,
pLog=0x641390, connectionBasePath=@0x7fff27ce2270,
subPath=@0x7fff27ce2280) at rdldExchangeServerDBusPosition.cpp:38
#5 0x0000000000416686 in RDLDDataExchangeServer::addExchangeMethod
(this=0x641dd0, type=1, basePath=@0x7fff27ce23b0,
subPath=@0x7fff27ce23a0, dBusType=1) at rdldExchangeServer.cpp:77
#6 0x000000000041e007 in RDLDGeneratePosition (this=0x63ea90, logLevel=2,
logFile=@0x7fff27ce24d0)
at rdldGeneratePosition.cpp:50
#7 0x000000000041ee70 in main (argc=1, argv=0x7fff27ce25e8) at main.cpp:88
The source that produces the above sigsev: (again only relevant stuff)
(RDLDExchangeServerStrategy is a set of virtual functions that needs to be
implemented by the child, nothing special in there)
class RDLDExchangeServerDBusCommon: public QDBusAbstractAdaptor, public
RDLDExchangeServerStrategy
{
Q_OBJECT
Q_PROPERTY(QString getNodeList READ getNodeList)
public:
RDLDExchangeServerDBusCommon (RDLDLog * pLog, QObject * obj);
~RDLDExchangeServerDBusCommon ();
void updateNode (int id, int x, int y, int z);
public slots:
QString getNodeList ();
QString getNodeInfo (int deviceId);
signals:
void updatedNode (int id, int x, int y, int z);
};
class RDLDExchangeServerDBusPosition : public RDLDExchangeServerDBusCommon
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "rdld.provide.position")
Q_PROPERTY(QString getTagList READ getTagList)
public:
RDLDExchangeServerDBusPosition(RDLDLog * pLog, QString connectionBasePath,
QString subPath);
~RDLDExchangeServerDBusPosition ();
public slots:
QString getTagList ();
QString getPosition (int tagId);
signals:
void updatedPosition (int tagId, int timestamp, double x, double y, double
z);
private slots:
void updatePosition (int tagId, int timestamp, float x, float y, float z);
void updateStrength (int deviceId, int tagId, int strength) {};
private:
QDBusConnection * dBus;
};
RDLDExchangeServerDBusPosition::RDLDExchangeServerDBusPosition (RDLDLog *
pLog, QString connectionBasePath, QString subPath)
: RDLDExchangeServerDBusCommon (pLog, this)
{
log = pLog;
// build up dbus connection:
dBus = new QDBusConnection ("");
dBus->connectToBus (QDBusConnection::ActivationBus, "");
if (!dBus->sessionBus().isConnected())
{
//print error
return ;
}
if (!dBus->sessionBus().registerService(connectionBasePath))
{
//print error
return ;
}
dBus->sessionBus().registerObject(QString ("/%1").arg(subPath), this,
QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportAllSignals);
}
--
[ signature omitted ]
On Tuesday 11 March 2008 18:58:35 Simon Schäfer wrote:
> On Tuesday 11 March 2008 15:31:16 Thiago Macieira wrote:
> first of all thanks for the fast answer.
>
> > On Tuesday 11 March 2008 15:17:38 Simon Schäfer wrote:
> > > QDBusConnection * dBus;
> >
> > Suggestion: don't use a pointer here. Use a QDBusConnection object.
> >
> > You'll have to initialise it in your constructor, though.
>
> I tried different ways and all lead to strange compile errors, only the
> pointer with creating a new object is working flawless.
> The other two ways:
> QDBus::sessionBus().... leads to:
> rdldExchangeServerDBusPosition.cpp:55: error: 'sessionBus' is not a member
> of 'QDBus'
Hmm... did you find that in our documentation? If so, can you point where,
because we need to fix it.
It's QDBusConnection::sessionBus().
> and
> using this in the header:
> QDBusConnection dBus;
> and changing all -> to . and delete the new leads to the following:
> In
> constructor
> 'RDLDExchangeServerDBusPosition::RDLDExchangeServerDBusPosition(RDLDLog*,
> QString, QString)':
> rdldExchangeServerDBusPosition.cpp:38: error: no matching function for call
> to 'QDBusConnection::QDBusConnection()'
Right. Like I said, you'll have to initialise it in your constructor
initialisation list. Probably like:
RDLDExchangeServerDBus::RDLDExchangeServerDBus(bool showPos)
: dBus(QDBusConnection::sessionBus())
{
...
}
> > > is there a way to let dBus->sessionBus().registerObject () only
> > > register specific methods and signals? or perhaps another method to do
> > > so?
> >
> > No. I recommend instead that you use multiple interfaces. Create two
> > Adaptor classes and instantiate the one you want to expose.
>
> I tried to implement the way you described but now I am getting a
> Segmentation fault when I run my application. Backtrace:
[snip]
> class RDLDExchangeServerDBusCommon: public QDBusAbstractAdaptor, public
> RDLDExchangeServerStrategy
> {
That's a multiple inheritance from QObject.
You should have two *extra* classes that derive from QDBusAbstractAdaptor.
Their only purpose is to expose the slots and signals. Then, in your
RDLDExchangeServerDBus constructor, you choose which one you want to
instantiate based on showPos. Something like:
if (showPos)
new RDLDExchangeServerDBusPosition(this);
else
new RDLDExchangeServerDBusTheOther(this);
--
[ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.
just a quick answer to solve the documentation problem, will look after the rest now. > > QDBus::sessionBus().... leads to: > > rdldExchangeServerDBusPosition.cpp:55: error: 'sessionBus' is not a > > member of 'QDBus' > > Hmm... did you find that in our documentation? If so, can you point where, > because we need to fix it. > > It's QDBusConnection::sessionBus(). > http://doc.trolltech.com/4.4beta/qdbusadaptorexample.html the code from the main.cpp -- [ signature omitted ]
> > class RDLDExchangeServerDBusCommon: public QDBusAbstractAdaptor, public
> > RDLDExchangeServerStrategy
> > {
>
> That's a multiple inheritance from QObject.
I cant see the multiple inheritance from QObject. As mentioned in the last
email, the RDLDExchangeServerStrategy is just a class that contains virtual
methods and does not contain any more than this:
class RDLDExchangeServerStrategy
{
public:
virtual ~RDLDExchangeServerStrategy () {};
virtual void updateNode (int id, int x, int y, int z) = 0;
virtual void updatePosition (int tagId, int timestamp, float x, float y,
float z) = 0;
virtual void updateStrength (int deviceId, int tagId, int strength) = 0;
};
Now what I build was:
RDLDExchangeServerDBusCommon:
storing the node methods that will be used by the two classes and is derived
from QDBusAbstractAdaptor and the purly virtual RDLDExchangeServerStrategy
the two classes which have the specific stuff are
RDLDExchangeServerDBusPosition
and
RDLDExchangeServerDBusStrength
both derived from the RDLDExchangeServerDBusCommon
In another class which handles all the Exchange strategies (not only DBus but
tcp as well)
it will instanciate those ala:
RDLDExchangeServerStrategy * exchangeStrat;
if (dBus && showPos)
exchangeStrat = new RDLDExchangeServerDBusPosition();
else if (dBus)
exchangeStrat = new RDLDExchangeServerDBusStrength();
else if (tcp)
exchangeStrat = new RDLDExchangeServerSSL();
thats why they have to be inherited from the RDLDExchangeServerStrategy. (the
above if/else is just to show what I mean in real code the strategies are
stored in a list so it can have multiple ways to answer for requests (right
now only dbus and tcp)
and now after writing all this I forgot what I initially wanted, ahh yes not
have to split the code or at least put the code that is exactly the same in
a different class and inherit from it.
I do not know why but now its working without the AbstractAdaptor, but with
the Q_SCRIPTABLE stuff back in. The initial stuff that caused all this is not
doable anyway(register only those methods i want to not all of a kind) so it
can stay without the DBusAdaptor stuff (I more and more think that I simply
do not understand how they work). So thank you for your patience and at least
we found a failure in the documentation, so all the traffic was not for
nothing
--
[ signature omitted ]