1

I'm using the Qt framework to make a GUI window, and what I do is open another application by creating a QProcess. I want to communicate with this second process, and the documentation says I can do this by writing to the process's stdin or reading from the process's stdout. I've tried many combinations and can't get it to work.

I can redirect the stdin and stdout of the new process to a file using:

process->setStandardOutputFile("d:\\outputfile.txt");
process->setStandardInputFile("d:\\inputfile.txt");

And then all cin, cout, cerr and clog commands read and write to the files. But I can't communicate directly from the Qt main window (the original application) to the new Qprocess that I create. I use:

process->write("HELLO_FROMMAINWINDOW");

and in the child application in the main loop I check stdin for any input:

fseek(stdin, 0, SEEK_END);
int num = ftell(stdin);
if (num > 0) logEntry("We have input");

The if condition is never true. Also I do std::cout in the main loop of the child process and in the Qt main window I try to read with:

 QByteArray str;
 str = process->readAll();
 str = process->readAllStandardOutput();

But they are always empty strings. I have read the documentation at http://doc.qt.io/qt-5/qprocess.html a few times but it's possible I'm not doing things right, as in maybe I'm forgetting to set something before trying to read and write.

Here is my attempt at a verifiable example:

My main GUI window header looks like this:

//#ifndef MAINWINDOW_H
//#define MAINWINDOW_H
#pragma once
//#endif // MAINWINDOW_H
#include <QMainWindow>

class QProcess;

namespace Ui
{
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget* parent = nullptr);
    ~MainWindow();
    Ui::MainWindow* ui;
    QProcess* engineProcess;
private slots:
    void on_pushButton_clicked();
    void on_pushButton_2_clicked();
};      // This is very much a stock setup with a simple main window.

Here is the main window cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QProcess>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}
MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked() // CALLED WHEN I CLICK THE START BUTTON
{// OPEN ENGINE PROCESS
    engineProcess = new QProcess(this);
    engineProcess->setWorkingDirectory("E:/Development/Programming/Projects/OpenGLEngine");
    int w = 1600 / 2, h = 900 / 2; // JUST GIVING RESOLUTION VALUES AS ARGUMENTS
    QStringList args = { "editor", std::to_string(w).c_str(), std::to_string(h).c_str() };
    //engineProcess->setStandardOutputFile("d:\\outputfile.txt");
    //engineProcess->setStandardInputFile("d:\\input.txt");
    // THE PREVIOUS TWO CALLS WORK FINE, stdout and stdin read and write them fine.

    engineProcess->start("E:/Development/Programming/Projects/OpenGLEngine/x64/Release/OpenGlEngine.exe", args);
    engineProcess->write("HELLO_FROMMAINWINDOW\n"); // DOESN'T GET DETECTED
}

void MainWindow::on_pushButton_2_clicked()
{
    const char* ch = "HEllo";
    quint64 charsWritten = engineProcess->write(ch, 5); // charsWritten equals 5

   auto result = engineProcess->write("Hello from the editor\n"); // 22 chars written, correct
   engineProcess->write("HELLO_FROMMAINWINDOW\n"); // DOESN'T GET DETECTED

   QByteArray str;
   str = engineProcess->readAll();
   str = engineProcess->readAllStandardOutput(); // EMPTY STRINGS RESULT
}

enter image description here

Zebrafish
  • 9,170
  • 2
  • 28
  • 78
  • Does adding a newline '\n' to the text written help at all? – G.M. Jan 08 '18 at 15:02
  • Does `ftell` do anything useful on a pipe? – Martin Bonner supports Monica Jan 08 '18 at 15:03
  • @G.M. No, I tried both with the reads and the writes. I'll try and post MCVE but it may be hard as there is a lot of code. – Zebrafish Jan 08 '18 at 15:08
  • @hyde Oh really? Did I miss something? The setStandardInputFile and setStandardOutputFile functions did work, that is the reading and writing to and from files worked fine. – Zebrafish Jan 08 '18 at 15:09
  • @hyde Oh do you mean that if you call any of those functions then the corresponding reads and writes from the Qt window won't work? Yeah I saw that, I commented them out. – Zebrafish Jan 08 '18 at 15:32
  • Ah, misunderstood, sorry, deleting comment – hyde Jan 08 '18 at 17:30
  • I managed to get parent Qt application to read the couts from my child process, and I don't know why. I rolled back to what I had before and the reading still occurs (I hate that). The writing stdin still doesn't get detected by the child process. I'm so tired, need sleep. – Zebrafish Jan 08 '18 at 17:43
  • I just had a look into my answer to [SO: Creating QT Application as GUI for existing console-based application on windows](https://stackoverflow.com/a/45209503/7478597). I used `QProcess::write()` and it worked well. Thus, I became suspicious about something else: `ftell(stdin)`. (I see that Marting Bonner found it questionable as well.) Concerning this I found: [SO: ftell( stdin ) causes illegal seek error](https://stackoverflow.com/a/2502549/7478597). – Scheff's Cat Jan 09 '18 at 11:23
  • If it is necessary for your console appl. to do reading _or_ something else, I guess, another approach could work better: Just make the read straight forward and blocking and do the other work in a separate thread. – Scheff's Cat Jan 09 '18 at 11:28
  • @Scheff If I call stdin.read() it acts the same way as std::cin >> var, ie., the program stops until there is something in the stdin buffer, like keyboard input. I thought the checking the stdin with ftell was a way to check. I wish it wouldn't stop the program when the buffer is empty, but I guess this is how it works. – Zebrafish Jan 09 '18 at 12:56
  • @Zebrafish Hence my 2nd comment concerning your console application: You could create a thread to read input (blocking) and do the other work concurrently (or, vice versa, create a thread to do the other work and read input blocking). I did something similar in my answer to [SO: I/O in concurrent program](https://stackoverflow.com/a/48097134/7478597) (although the intention was a bit different). I must admit that sample wouldn't work nice if used with a Qt wrapper - it's rather designed for direct input. However, it might illustrate/inspire the "input concurrent to other work" topic. – Scheff's Cat Jan 09 '18 at 13:03
  • @Zebrafish Better matching samples, you can find with google "C++ non-blocking stdin". (I just checked it out.) Some of the found answers (at SO and elsewhere) are based on the same idea of input in an extra thread. – Scheff's Cat Jan 09 '18 at 13:29

0 Answers0