Необходимо запустить дочерний процесс, вводить и выводить данные из него последовательно. Однако, если дочерний процесс имеет цикл ввода, получить от него данные не удается. Код запуска процесса и соединения со слотом:
RSGui::RSGui(QWidget *parent)
: QMainWindow(parent), rsgCommandBuilder(CommandBuilder::getInstance())
{
ui.setupUi(this);
rsgProcess = new QProcess();
connect(rsgProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(printOutput()));
rsgProcess->start("C://infinityLoop");
rsgProcess->waitForStarted(-1);
rsgProcess->write("1");
rsgProcess->write("2");
rsgProcess->write("8");
rsgProcess->closeWriteChannel();
rsgProcess->waitForFinished();
rsgProcess->kill();
}
void RSGui::printOutput()
{
qDebug() << "call";
ui.plainTextEdit->appendPlainText(rsgProcess->readAllStandardOutput());
}
Запускаемый дочерний процесс (infinityLoop.exe):
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int i = 0;
while (i != 8)
{
cin >> i;
cout << "Entered: " << i << endl;
}
return 0;
}
Вывод qDebug() не понятен, много раз обращается к слоту:
В данном случае, для корректной записи в поток ввода дочернего процесса, необходимо было добавлять символ переноса строки в конце записи '\n', так как аргумент метода write() - это const char *data, который не заботится о его наличии. О потоке ввода cin.
Пример рабочего кода:
rsgProcess->write("1\n");
rsgProcess->write("2\n");
rsgProcess->write("8\n");
Вывод в plainTextEdit:
Несколько call в выводе можно объяснить тем, что в дочернем процессе вы не проверяете EOF, поэтому после .closeWriteChannel(); вызова второй и последующие cin >> i сразу же с ошибкой возвращаются, позволяя циклу несколько итераций совершить в дочернем процессе.
Если добавить проверку на EOF в дочерний цикл:
#include <iostream>
int main()
{
for(int i; std::cin >> i && i != 8; )
std::cout << "Entered: " << i << std::endl;
}
тогда вы должны увидеть call только раз.
.write("1"); .write("2"); .write("8"); в вашем случае равнозначны одному .write("128"); -- канал (pipe) принимает байты (это поток байт, а не сообщений). В родителе может быть исходящий буфер, в дочернем процессе может быть входящий буфер, плюс cin >> i ждёт или пробела или EOF/ошибки, то есть в вашем случае пока .closeWriteChannel(); не вызван cin не возвращается. Вы вероятно хотели: .write("1 2 8") написать.
waitForStarted(), waitForFinished() могут заморозить ваше GUI ("Calling this function from the main (GUI) thread might cause your user interface to freeze."). Вы можете вместо этого подключить соответствующие сигналы. К примеру, используя qt5 синтаксис для сигналов и c++11 lambda:
QProcess p;
p.setProcessChannelMode(QProcess::MergedChannels); // merge child's stdout/stderr
// process started; write some input to the child process
QObject::connect(&p, &QProcess::started, [&]() {
QTextStream stream {&p};
for (int i : {1, 2, 8}) stream << i << " ";
stream.flush();
p.closeWriteChannel(); // no more input
});
// process' output is ready
QObject::connect(&p, &QProcess::readyReadStandardOutput, [&]() {
qDebug() << "<" << p.readAllStandardOutput() << ">";
});
// process finished
QObject::connect(&p, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), //XXX use qOverload<> in Qt5.7+
[&](int exitCode, QProcess::ExitStatus) {
qDebug() << "finished with " << exitCode;
});
//XXX use connect(&p, &QProcess::errorOccurred,..
p.start("./child"); //XXX *nix
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости