Получение ответа от QProcess

504
03 мая 2017, 11:44

Необходимо запустить дочерний процесс, вводить и выводить данные из него последовательно. Однако, если дочерний процесс имеет цикл ввода, получить от него данные не удается. Код запуска процесса и соединения со слотом:

   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() не понятен, много раз обращается к слоту:

Answer 1

В данном случае, для корректной записи в поток ввода дочернего процесса, необходимо было добавлять символ переноса строки в конце записи '\n', так как аргумент метода write() - это const char *data, который не заботится о его наличии. О потоке ввода cin.

Пример рабочего кода:

rsgProcess->write("1\n");
rsgProcess->write("2\n");
rsgProcess->write("8\n");

Вывод в plainTextEdit:

Answer 2

Несколько 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
READ ALSO
Помогите пожалуйста перевести код с Pascal на С++ [требует правки]

Помогите пожалуйста перевести код с Pascal на С++ [требует правки]

Помогите пожалуйста перевести код с Pascal на С++

310
Проблема с inline

Проблема с inline

Здравствуйте! Пишу обработчик для WM_MOUSEMOVE для своего элемента UIЕсть массив этих элементов UI Сol *col[100000]={NULL}, часть которого не NULL

311
Смена языка сообщения error_code в boost

Смена языка сообщения error_code в boost

Когда я получаю ошибку в бусте, я могу ее прочитать, вызвав метод error_code::message()Я бы хотел, чтобы она выводилась на английском (сейчас она выводится...

330
Стэк не работает

Стэк не работает

Хотелось бы вывести 4 3 2 1 0Но ничего не выводит

324