[Interest] Heavily Commented Example: Simple Single Frontend with Two BackendsLow,

d3fault d3faultdotxbe at gmail.com
Fri Oct 26 11:45:03 CEST 2012

tl;dr: How can I use the Q_OBJECT macro within a pre-processor macro?

So I've got the rewrite 99% done, and I mean it looks a heck of a lot
cleaner than the first example. Fixed a lot of typos in comments too.

That 1% is proving to be a problem though :(.

If I don't use that "template" idea I was talking about, then it works
easy. The thing is, I don't want to ever have to sub-class QThread.
Why? Simple: Business logic does not belong in a QThread sub-class. I
want it to be re-usable to the point where I don't have to sub-class
QThread for every object type.

So nao I'm asking for halp.

Templates and MOC don't play nice together. The only hacky workaround
I got working with templates/moc required me to sub-class a templated
class, guh. Might as well sub-class QThread.

I tried with a pre-processor macro, but the Q_OBJECT macro within my
macro messes things up :(.

The only problem I'm having is one of string substitution, lmfao.

Here's what my non-working macro currently looks like:

	class UserObjectType##OnThreadHelper : public QThread \
	{ \
	public: \
		explicit UserObjectType##OnThreadHelper(QObject *parent = 0) :
QThread(parent) { } \
		virtual void run() \
		{ \
			UserObjectType qobj; \
			emit object##UserObjectType##IsReadyForConnectionsOnly(&qobj); \
			exec(); \
		} \
	signals: \
		void object##UserObjectType##IsReadyForConnectionsOnly(&qobj); \

^^^I hope the formatting doesn't mess up when I post this. I am
escaping all the newlines properly.


In your header, after #include'ing both the macro and the QObject
inherited types you want to work with on backend threads, you do:
//etc. Way easier than overriding QThread::run() for each type...

Which creates the classes that you then add to your class as members
(the one that "hasA" QThread/backend-object... in my example: the
"test" class):

	SimpleBackend1OnThreadHelper m_Backend1ThreadHelper;
	SimpleBackend2OnThreadHelper m_Backend2ThreadHelper;

then connect and start:

//in my "test" class's constructor
this, SLOT(handleSimpleBackend1ReadyForConnectionsOnly(SimpleBackend1*)));
this, SLOT(handleSimpleBackend2ReadyForConnectionsOnly(SimpleBackend2*)));

and to stop:
//handleAboutToQuit or similar

...which causes the object of the type that you pass into the macro to
go out of scope after exec() returns. Qt's signals/slots handles the
object's disappearance with no problem (signals/slots are smart,

But that's the thing: the macro doesn't work because of the Q_OBJECT
macro within it. I also tried Q_##OBJECT to try to get it to evaluate
twice... except that doesn't work because MOC runs before the
preprocessor does.

I could trivially add a build step that does string replacing, but
then it isn't very portable/re-usable :(.

Would be nice to be able to do clean threading with just:

#include "objectonthreadhelper.h" //the macro
MyCustomObjectTypeThreadHelper m_MyCustomObjectTypeThreadHelper;
this, SLOT(handleMyCustomObjectTypeReadyForConnectionsOnly(MyCustomObjectType*)));

No more .moveToThread()... which doesn't let your object's constructor
run on the thread
No more overriding QThread::run()... business logic does not belong in
there... and I don't want to do copy/paste programming for every
object type I want on a backend thread

Anyone have a portable solution to that string substitution problem?


More information about the Interest mailing list