External process from Qml
-
is it possible to call an external process from qml ?
Not directly but you can create a C++ component and expose it to QML and make it execute the external processes
@p3c0 thanks for the reply...
yea i am doing the same now... i am using a C++ class and Qprocess to start another process....the new process gives me a string (it is a command said in live microphone) which i pass it through signal back to the qml...but what is happening is..when i call the c++ function from qml, the control doesn't wait until the function is over, it continues to print some debug statements, which i have given after that function call -
@p3c0 ya sure.
here is the c++ code#include "ProcessWidget.h" ProcessWidget::ProcessWidget(QWidget *parent) : QWidget(parent) { } void ProcessWidget::vStartProcess() { qDebug()<<"entered the function"<<endl; const QString program = QStringLiteral("/home/ubuntu/Documents/Sample_Examples_Qt_Qml/VoiceRecognition/VoiceRecognition"); myProcess = new QProcess; connect(myProcess,SIGNAL(readyReadStandardError()),this,SLOT(vEndProcess())); connect(myProcess,SIGNAL(finished(int)),myProcess,SLOT(deleteLater())); myProcess->start(program); qDebug()<<"process started waiting for output"<<endl; connect(this,&ProcessWidget::destroyed,myProcess,&QProcess::kill); } void ProcessWidget::vEndProcess() { const QString processOut = QString::fromLatin1(myProcess->readAllStandardError()); qDebug()<<"output>>>>"<<processOut<<endl; const QRegularExpression regXp("Received Command:s*(.+)"); const auto regXpMatch = regXp.match(processOut); if(regXpMatch.hasMatch()){ qDebug() << "Output of regular exp is: "<< regXpMatch.captured(1); signalData= regXpMatch.captured(1); qDebug()<<"signal data is >>"<<signalData<<endl; emit playmusicsignal(signalData); } } ProcessWidget::~ProcessWidget() { }
-
-
@p3c0 Sir i used execute instead of start but...i am not able to pass the output which i got from the new process, back to qml...what may be the problem ?
my code#include "ProcessWidget.h" ProcessWidget::ProcessWidget(QWidget *parent) : QWidget(parent) { } void ProcessWidget::vStartProcess() { qDebug()<<"entered the function"<<endl; const QString program = QStringLiteral("/home/ubuntu/Documents/Sample_Examples_Qt_Qml/VoiceRecognition/VoiceRecognition"); myProcess = new QProcess; connect(myProcess,SIGNAL(readyReadStandardError()),this,SLOT(vEndProcess())); connect(myProcess,SIGNAL(finished(int)),myProcess,SLOT(deleteLater())); connect(this,&ProcessWidget::destroyed,myProcess,&QProcess::kill); myProcess->execute(program); // myProcess->waitForStarted(30000); qDebug()<<"process started waiting for output"<<endl; } void ProcessWidget::vEndProcess() { const QString processOut = QString::fromLatin1(myProcess->readAllStandardError()); qDebug()<<"output>>>>"<<processOut<<endl; const QRegularExpression regXp("Received Command:s*(.+)"); const auto regXpMatch = regXp.match(processOut); if(regXpMatch.hasMatch()){ qDebug() << "Output of regular exp is: "<< regXpMatch.captured(1); signalData= regXpMatch.captured(1); qDebug()<<"signal data is >>"<<signalData<<endl; emit playmusicsignal(signalData); } } ProcessWidget::~ProcessWidget() { }
in the above code, i didn't get any debug statements in console from vEndProcess function
-
Maybe I'm being silly here but since you are running what looks like the Hello Speak Example why do you start it as a separate process rather than a separate thread?
-
Maybe I'm being silly here but since you are running what looks like the Hello Speak Example why do you start it as a separate process rather than a separate thread?
-
-
-
That's because you block the event loop that you need to read. Use
void ProcessWidget::vStartProcess() { qDebug()<<"entered the function"<<endl; const QString program = QStringLiteral("/home/ubuntu/Documents/Sample_Examples_Qt_Qml/VoiceRecognition/VoiceRecognition"); myProcess = new QProcess; QEventLoop blockLoop; connect(myProcess,SIGNAL(readyReadStandardError()),this,SLOT(vEndProcess())); connect(myProcess,SIGNAL(finished(int)),myProcess,SLOT(deleteLater())); connect(myProcess,SIGNAL(finished(int)),&blockLoop,SLOT(quit())); connect(this,&ProcessWidget::destroyed,myProcess,&QProcess::kill); myProcess->start(program); qDebug()<<"process started waiting for output"<<endl; blockLoop.exec(); }
-
That's because you block the event loop that you need to read. Use
void ProcessWidget::vStartProcess() { qDebug()<<"entered the function"<<endl; const QString program = QStringLiteral("/home/ubuntu/Documents/Sample_Examples_Qt_Qml/VoiceRecognition/VoiceRecognition"); myProcess = new QProcess; QEventLoop blockLoop; connect(myProcess,SIGNAL(readyReadStandardError()),this,SLOT(vEndProcess())); connect(myProcess,SIGNAL(finished(int)),myProcess,SLOT(deleteLater())); connect(myProcess,SIGNAL(finished(int)),&blockLoop,SLOT(quit())); connect(this,&ProcessWidget::destroyed,myProcess,&QProcess::kill); myProcess->start(program); qDebug()<<"process started waiting for output"<<endl; blockLoop.exec(); }
-
@p3c0 thanks for the reply...
yea i am doing the same now... i am using a C++ class and Qprocess to start another process....the new process gives me a string (it is a command said in live microphone) which i pass it through signal back to the qml...but what is happening is..when i call the c++ function from qml, the control doesn't wait until the function is over, it continues to print some debug statements, which i have given after that function call@Naveen_D said in External process from Qml:
but what is happening is..when i call the c++ function from qml, the control doesn't wait until the function is over, it continues to print some debug statements, which i have given after that function call
@Naveen_D said in External process from Qml:
if i use the EventLoop it is not returning control
I'm not sure I understand what you want to achieve. Do you want the process to act synchronously (loop until process is over) or asynchronously (return control almost immediately to the main app)?
-
@Naveen_D said in External process from Qml:
but what is happening is..when i call the c++ function from qml, the control doesn't wait until the function is over, it continues to print some debug statements, which i have given after that function call
@Naveen_D said in External process from Qml:
if i use the EventLoop it is not returning control
I'm not sure I understand what you want to achieve. Do you want the process to act synchronously (loop until process is over) or asynchronously (return control almost immediately to the main app)?
@VRonin the scenario is..when i call the c++ function from qml it should start the process...through which i get the output and will pass the output through a signal back to qml. till the process is not completed it should not return back to main app(i.e Qml app).
Now i am getting the output to my console but i am not able to send it as shown in the above code. -
@VRonin the scenario is..when i call the c++ function from qml it should start the process...through which i get the output and will pass the output through a signal back to qml. till the process is not completed it should not return back to main app(i.e Qml app).
Now i am getting the output to my console but i am not able to send it as shown in the above code.@Naveen_D Why should it not return? What you are trying to do is not how Qt apps should work. You should use signals/slots: you start the process, connect signals/slots and as soon as there is input from the process you handle it in the slot.
-
@Naveen_D Why should it not return? What you are trying to do is not how Qt apps should work. You should use signals/slots: you start the process, connect signals/slots and as soon as there is input from the process you handle it in the slot.
-
@jsulm Sorry sir i didn't get...is the above code wrong which i have posted ? or what changes i need to do ?
One more doubt..how to compare a string in Qml...like in Qt we do (str=="some string")
@Naveen_D ProcessWidget::vStartProcess is currently blocking, why? Why not just start the process, connect signals/slots and return from ProcessWidget::vStartProcess ?
void ProcessWidget::vStartProcess() { qDebug()<<"entered the function"<<endl; const QString program = QStringLiteral("/home/ubuntu/Documents/Sample_Examples_Qt_Qml/VoiceRecognition/VoiceRecognition"); myProcess = new QProcess; connect(myProcess,SIGNAL(readyReadStandardError()),this,SLOT(vEndProcess())); connect(myProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(processStandardOutput())); connect(myProcess,SIGNAL(finished(int)),myProcess,SLOT(deleteLater())); connect(this,&ProcessWidget::destroyed,myProcess,&QProcess::kill); myProcess->start(program); }
processStandardOutput() will be called as soon as the process is writing something to standard output.