0
votes

We're using a really old version of Qt, 1.1, I think. Circa 2000. It's for in-house use only, so there's little concern to upgrade at this time. Program is built on Windows using Visual Studio 2005. I know very little of Qt, other than what I've been researching over the last couple days.

The (very basic) architecture is:

  • main() creates a QApplication instance.
  • main() also creates a pointer to a custom subclass of QWidget called Wizard.
  • Wizard creates a number of Controller objects, which are subclassed from QThread.

I am trying to implement a new class / thread, launched from main(), the purpose of which is to monitor a service and signal an action to be carried out in the Controller objects / threads.

My new class / Thread definition:

#include "qthread.h"

class ServiceMonitor : public QThread 
{
    Q_OBJECT

public:
   ServiceMonitor(int p) : port(p) {}
   ~ServiceMonitor() {};

private:
   void run();
   void TerminateProgram();

signals:
   void SomethingBadHappened();

private:
   int port;
};

And in my cpp file:

void ServiceMonitor::TerminateProgram()
{
   ...
   emit SomethingBadHappened();
   ...
}

When I compile the app, I receive a linker error:

error LNK2019: unresolved external symbol "protected: void __thiscall ServiceMonitor::SomethingBadHappened(void)"
 (?SomethingBadHappened@ServiceMonitor@@IAEXXZ) referenced in function "private: void __thiscall ServiceMonitor::TerminateProgram(void)"
 (?TerminateProgram@ServiceMonitor@@AAEXXZ) ServiceMonitor.obj  

I notice that all of our other objects (which have signals) are not derived from Qthread, so I have no examples to follow. The rest (which do use signals) are derived from QWidget or QObject). I notice those use the moc.exe in a custom compile step to generate an output file which is included in the project. I did try to run moc on the header containing the class above and including the output file, where I received:

Error   1   error C2039: 'className' : is not a member of 'QThread'
Error   2   error C3861: 'badSuperclassWarning': identifier not found
Error   3   error C2039: 'staticMetaObject' : is not a member of 'QThread'
Error   4   error C3861: 'activate_signal': identifier not found

What am I doing wrong?

EDIT:

Tried RA's proposal, worked a treat (Once I remembered to include qobject.h). Thanks!

New definition:

#include "qthread.h"
#include "qobject.h"

class ServiceMonitor : public QObject, public QThread
...
2
You can only define signals, use the Q_OBJECT macro and run moc.exe on classes that inherit from QObject. The QThread class did not inherit from QObject prior to Qt 4.0, which is why you're getting errors. You can try to use multiple inheritance (i.e., class ServiceMonitor : public QObject, public QThread -- note that QObject must be first). - RA.
Can you post your updated code? The errors make it seem like you're not including qobject.h. - RA.
Yep, that did it. Repost your comment as an answer and I shall accept. Thank you! - Jon

2 Answers

2
votes

For versions of Qt prior to Qt 4.0, the QThread class did not inherit from QObject. As such, if you want to create a class derived from QThread that has signals, you must inherit from both QObject and QThread:

#include "qobject.h"
#include "qthread.h"

class ServiceMonitor : public QObject, public QThread 
{
    Q_OBJECT
    // Rest of class
};

Note that QObject must be listed as the first class derived from.

Also remember to run moc on the class and to compile the generated moc code.

0
votes

The missing part is the implementation of all the signals, and of the staticMetaObject structure that's declared as part of Q_OBJECT macro. Those are generated by moc. Moc-ing of the headers would normally be handled by a Qt add-in for Visual Studio. Unfortunately, there are no Qt-5 add-ins for VS 2005.

Your options are, in order of decreasing desirability.

  1. Use qmake to generate a VS 2005 project file that invokes moc for you, and includes the necessary files. That would be the best way for you to use Qt.

  2. Manually run moc on all of the header files that contain the Q_OBJECT macro, and add the generated code to your project.

  3. Upgrade to at least VS 2008 (not Express), so that you can use the Qt 5 add-in.

  4. Try Qt 4, which has an add-in for VS 2005.

Since you can have multiple versions of Qt installed at the same time, you can pursue multiple approaches in parallel. For example, #1 and #4.