Problem with Connect and Lambda functions
-
wrote on 16 Jan 2023, 12:48 last edited by
Hello. It is my first time using a lambda function in QObject::connect
QProcess *process = new QProcess(this); QObject::connect(process, &QProcess::finished, this, [this, process](){ int id = m_processes.key(process); emit processFinished(id); });
It gives me some errors, and I dont know how to solve it
Any idea? What I am doing wrong??
-
@Chris-Kawa I am using Qt 5.15.2 and compiler mingw81_32
@JonexElectronic said:
I am using Qt 5.15.2
Oh, that makes sense. In Qt5 there are two overloads of
QProcess::finished
. They were merged in Qt 6. In Qt5 you have to explicitly choose one, so eitherconnect(process, qOverload<int>(&QProcess::finished), this, [this, process](){
or
connect(process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, [this, process](){
-
The error is in
procesos.cpp
. Very hard to guess, without clairvoyant abilities.
Maybe you want to post all your code, including the header? -
Is
ProcessController
derived from QObject? -
Is
ProcessController
derived from QObject?wrote on 16 Jan 2023, 15:47 last edited by@Chris-Kawa Yes it is
-
The error is in
procesos.cpp
. Very hard to guess, without clairvoyant abilities.
Maybe you want to post all your code, including the header?wrote on 16 Jan 2023, 15:53 last edited by JonexElectronic@Axel-Spoerl
I am sure that the problem is in lambda functions because if I comment this line it compile perfectprocess.h
class ProcessController : public QObject { Q_OBJECT public: explicit ProcessController(QObject *parent = nullptr); ~ProcessController(); int addProcess(const QString &command, const QStringList &arguments); void startProcess(int id); void stopProcess(int id); signals: void processFinished(int id); private: QMap<int, QProcess*> m_processes; QMap<int, QString> m_command; QMap<int, QStringList> m_arguments; int m_nextId; };
process.cpp
ProcessController::ProcessController(QObject *parent) : QObject(parent) { m_nextId = 0; } ProcessController::~ProcessController() { for (auto process : m_processes) { process->terminate(); process->waitForFinished(); delete process; } m_processes.clear(); m_command.clear(); m_arguments.clear(); } int ProcessController::addProcess(const QString &command, const QStringList &arguments) { QProcess *process = new QProcess(this); connect(process, &QProcess::finished, this, [this, process](){ int id = m_processes.key(process); emit processFinished(id); }); int id = m_nextId++; m_processes[id] = process; m_command[id]= command; m_arguments[id] = arguments; return id; } void ProcessController::startProcess(int id) { if(!m_processes.contains(id)) return; QProcess *process = m_processes[id]; QString command = m_command[id]; QStringList arguments = m_arguments[id]; process->start(command, arguments); } void ProcessController::stopProcess(int id) { if(!m_processes.contains(id)) return; QProcess *process = m_processes[id]; process->terminate(); process->waitForFinished(); }
-
wrote on 16 Jan 2023, 16:14 last edited by
Change:
connect(process, &QProcess::finished, this, [this, process](){ int id = m_processes.key(process); emit processFinished(id); });
To :
connect(process, &QProcess::finished, [this, process](){ int id = m_processes.key(process); emit processFinished(id); });
You don't need to specify destination object in a functor connect.
-
@Axel-Spoerl
I am sure that the problem is in lambda functions because if I comment this line it compile perfectprocess.h
class ProcessController : public QObject { Q_OBJECT public: explicit ProcessController(QObject *parent = nullptr); ~ProcessController(); int addProcess(const QString &command, const QStringList &arguments); void startProcess(int id); void stopProcess(int id); signals: void processFinished(int id); private: QMap<int, QProcess*> m_processes; QMap<int, QString> m_command; QMap<int, QStringList> m_arguments; int m_nextId; };
process.cpp
ProcessController::ProcessController(QObject *parent) : QObject(parent) { m_nextId = 0; } ProcessController::~ProcessController() { for (auto process : m_processes) { process->terminate(); process->waitForFinished(); delete process; } m_processes.clear(); m_command.clear(); m_arguments.clear(); } int ProcessController::addProcess(const QString &command, const QStringList &arguments) { QProcess *process = new QProcess(this); connect(process, &QProcess::finished, this, [this, process](){ int id = m_processes.key(process); emit processFinished(id); }); int id = m_nextId++; m_processes[id] = process; m_command[id]= command; m_arguments[id] = arguments; return id; } void ProcessController::startProcess(int id) { if(!m_processes.contains(id)) return; QProcess *process = m_processes[id]; QString command = m_command[id]; QStringList arguments = m_arguments[id]; process->start(command, arguments); } void ProcessController::stopProcess(int id) { if(!m_processes.contains(id)) return; QProcess *process = m_processes[id]; process->terminate(); process->waitForFinished(); }
@JonexElectronic It looks ok and compiles fine for me. The error is about the old syntax connect, while you're using the new one. What Qt version and compiler do you get that error on? Which C++ version are you using?
@fcarney While not strictly necessary, it's always a good idea to pass the context object parameter. In this case we're within the same class, but in general if you use an object in the lambda and it dies before the connection does it's possible to invoke the lambda with a dead object. So passing the object as context is a good idea so the connection is severed when the object dies.
-
@JonexElectronic It looks ok and compiles fine for me. The error is about the old syntax connect, while you're using the new one. What Qt version and compiler do you get that error on? Which C++ version are you using?
@fcarney While not strictly necessary, it's always a good idea to pass the context object parameter. In this case we're within the same class, but in general if you use an object in the lambda and it dies before the connection does it's possible to invoke the lambda with a dead object. So passing the object as context is a good idea so the connection is severed when the object dies.
wrote on 16 Jan 2023, 17:20 last edited by@Chris-Kawa I am using Qt 5.15.2 and compiler mingw81_32
-
Hello. It is my first time using a lambda function in QObject::connect
QProcess *process = new QProcess(this); QObject::connect(process, &QProcess::finished, this, [this, process](){ int id = m_processes.key(process); emit processFinished(id); });
It gives me some errors, and I dont know how to solve it
Any idea? What I am doing wrong??
wrote on 16 Jan 2023, 17:23 last edited by JonB@JonexElectronic
As @Chris-Kawa says, please confirm just which version of Qt you are using? E.g. Qt 4 would not be good! UPDATE OK, 5.15 is fine.But also, just in case, delete the build output directory and recompile from scratch. Adding
Q_OBJECT
macro can cause a problem, though usually at link time. You have a compile error, but just in case make sure you have recompiled from absolute scratch.... -
@Chris-Kawa I am using Qt 5.15.2 and compiler mingw81_32
@JonexElectronic said:
I am using Qt 5.15.2
Oh, that makes sense. In Qt5 there are two overloads of
QProcess::finished
. They were merged in Qt 6. In Qt5 you have to explicitly choose one, so eitherconnect(process, qOverload<int>(&QProcess::finished), this, [this, process](){
or
connect(process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, [this, process](){
-
@JonexElectronic said:
I am using Qt 5.15.2
Oh, that makes sense. In Qt5 there are two overloads of
QProcess::finished
. They were merged in Qt 6. In Qt5 you have to explicitly choose one, so eitherconnect(process, qOverload<int>(&QProcess::finished), this, [this, process](){
or
connect(process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, [this, process](){
wrote on 17 Jan 2023, 11:22 last edited by@Chris-Kawa said in Problem with Connect and Lambda functions:
connect(process, qOverload<int>(&QProcess::finished), this, this, process{
Thanks!! It works
-
@Chris-Kawa said in Problem with Connect and Lambda functions:
connect(process, qOverload<int>(&QProcess::finished), this, this, process{
Thanks!! It works
@JonexElectronic Cool, no problem. The overload with just
int
is the one that is deprecated, so although more typing, it's better to use the other one. Fewer changes if you decide to update to Qt6 at some point. But either one is fine for now.
1/12