Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 2

Qt-interest Archive, March 2008
register single objects in a D-Bus interface


Message 1 in thread

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 ] 

Message 2 in thread

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.


Message 3 in thread

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 ] 

Message 4 in thread

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.


Message 5 in thread

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 ] 

Message 6 in thread

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