'Qt5 + CMake + QThread: the signal from abstract base class is not connected to the slot in another thread
I implemented a hierarchy of classes to handle sensor interaction in a multithreaded QThread-based manner, as how it is recommended in Qt documentation. Here I have the header file types.h with the abstract base sensor reader class:
#include <QtCore>
class QAbstractSensorReader: public QObject
{ Q_OBJECT
protected slots:
virtual void ReadData() = 0;
public slots:
virtual void RunPoll() = 0;
signals:
void acquired();
};
In the file serial.h implementing the actual sensor reader I have the following text:
#include "types.h"
class QBaseSerialSensorReader: public QAbstractSensorReader
{
Q_OBJECT
private:
/*===*/
protected:
QTextStream ttyout;
QTimer* poll_timer;
virtual void ReadData();
public:
QBaseSerialSensorReader(const QString device);
virtual ~QBaseSerialSensorReader();
virtual void RunPoll();
};
The signal acquired() is emitted in the ReadData() handler when the data packet is assembled completely during the sensor poll. The slot RunPoll() is used to initialize and start a timer. Then I implemented the controller class:
#include "serial.h"
class QSensor: public QObject
{
Q_OBJECT
private:
QThread reader_thread;
QBaseSerialSensorReader* reader;
public:
QSensor()
{
reader = new QBaseSerialSensorReader();
reader->moveToThread(&reader_thread);
connect(&reader_thread, &QThread::finished, reader, &QObject::deleteLater);
connect(this, &QSensor::RunReader, reader, &QAbstractSensorReader::RunPoll);
connect(reader, &QBaseSerialSensorReader::acquired, this, &QSensor::Packet);
reader_thread.start();
}
void Start() {emit RunReader();}
virtual ~QSensor();
public slots:
void Packet(){ttyout << "ACQUIRED!";}
signals:
void RunReader();
};
Then the application:
#include "controller.h"
int main(int argc, char** args)
{
QCoreApplication app(argc, args);
QSensor sensor();
sensor.Start();
sleep(10);
return 0;
}
exploits the hierarchy.
The CMake file contains the following text:
find_package(Qt5 REQUIRED COMPONENTS Core SerialPort)
set(CMAKE_AUTOMOC ON)
qt5_wrap_cpp(MOC_SOURCES
include/types.h
include/serial.h
include/contoller.h
)
set(LIBRARY_SOURCES
${MOC_SOURCES}
src/util.cpp
src/serial.cpp
src/controller.cpp
)
add_library(sensor-serial SHARED ${LIBRARY_SOURCES})
target_link_libraries(sensor-serial Qt5::Core Qt5::SerialPort)
add_executable(library-init-test
tests/library-init-test.cpp
)
target_link_libraries(library-init-test
Qt5::Core Qt5::SerialPort
sensor-serial
)
The problem is that the signal QSensor::RunReader is successfully connected to QAbstractSensorReader::RunPoll slot: the virtual function QBaseSerialSensorReader::RunPoll() is called. The timer is also started and the ReadData() function works emitting the acquired signal. But this signal then does not seem to be connected to the QSensor::Packet() slot neither from QAbstractSensorReader nor from QBaseSerialSensorReader namespace.
Could you please try to explain what wrong is happening with this code?
Solution 1:[1]
You are not entering application event loop. Remove sleep from main function and call QCoreApplication::exec. I.e. replace these lines
sleep(10);
return 0;
with
return app.exec();
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | talamaki |
