Имеется класс Controller, который управляет некоторым воркерам Worker и используем логику взаимодействия на сигналах и слотах.
Насколько я понимаю, для того, чтобы это работало требуется QEventsLoop, который предоставляется QCoreApplication.
Controller нужно обернуть в свой класс и свою библиотеку. Как это правильно сделать?
Вот такое наивное решение попытался сделать: сунуть QAppliсation в std::tread. Возникло предупреждение " QApplication was not created in the main() thread.". При запуске сигналы и слоты не работают в библиотеке.
class Controller : public QObject
{
Q_OBJECT
public:
explicit Controller(QObject *parent = nullptr);
int getNumber() {return mNumber;}
void setPong(int n);
signals:
void ping();
private:
std::atomic<int> mNumber {0};
Worker mWorker;
QThread *mWorkerThread;
};
void MainEventLoopStart()
{
int j = 0;
char *c = nullptr;
QCoreApplication app(j, &c);
app.exec();
}
Controller::Controller(QObject *parent) : QObject(parent)
{
std::thread th(MainEventLoopStart);
th.detach();
mWorkerThread = new QThread;
mWorker.moveToThread(mWorkerThread);
connect(mWorkerThread, &QThread::finished, &mWorker, &QObject::deleteLater);
connect(this, &Controller::ping, &mWorker, &Worker::setPing);
connect(&mWorker, &Worker::pong, this, &Controller::setPong);
mWorkerThread->start();
emit ping();
}
void Controller::setPong(int n)
{
qDebug() << "setPong(" << n << ")";
mNumber = n;
if(mNumber<100) emit ping();
}
Класс библиотеки
class Qlibrary
{
public:
Qlibrary();
int getNumber();
private:
Controller *mController;
};
Qlibrary::Qlibrary()
{
mController = new Controller;
}
int Qlibrary::getNumber()
{
return mController->getNumber();
}
Воркер
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
signals:
void pong(int);
public slots:
void setPing();
private:
int mBNumber {0};
};
Worker::Worker(QObject *parent) : QObject(parent) {}
void Worker::setPing()
{
qDebug() << "setPing";
QThread::usleep(100);
mBNumber += 1;
emit pong(mBNumber);
}
Здравствуйте, Zhendos, Вы писали:
Z>По идее QCoreApplication должен быть создан до всех объектов Qt,
Z>и он должен быть создан один раз за время существования процесса который
Z>подгрузил библиотеку.
Нда ... тогда точно есть проблема. Допустим я в qlibrary ввожу функцию, которая заводит Qt-е классы:
void runApp()
{
std::thread th
(
[&]
{
int j = 0;
char *c = nullptr;
QCoreApplication app(j, &c);
Controller controller; // or new Controller
app.exec();
}
);
th.detach(); // may bee join()
}
И если это GUI, то все возможно будет хорошо, т.к. виджет запустится и можно будет управлять всем этим хозяйством.
Но, мне нужно управлять в консольном приложении интерфейсом Controller, и здесь абсолютно не понятно как вытащить указатель на Control из другого потока.
вроде сообразил, через ссылку на указатель можно управлять Controller:
void runApp(Controller* &controller)
{
std::thread th
(
[&]
{
int argc = 0;
char *argv = nullptr;
QCoreApplication app(argc, &argv);
controller = new Controller;
app.exec();
}
);
th.detach();
}