fonZ fonZ - 1 month ago 24
C Question

Qt 5 and QProcess redirect stdout with signal/slot readyRead

This problem is bothering me because it should work, but sadly it does not.
What i try to achieve is to read the standard output of a certain process and make another process handle it i.e. print it out.

The process that produces output looks like this:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

int main() {
for (int i = 0; i < 100; i++) {
printf("yes %d\n",i);
fflush(stdout);
sleep(1);
}
return 0;
}


The process is started in another application like this:

#include <QProcess>
...
QProcess * process = new QProcess;
SomeClass * someClass = new SomeClass(process);
connect(process,SIGNAL(readyRead()),someClass,SLOT(onReadyRead()));

process->start("../Test/Test",QStringList());
if (!process->waitForStarted(4000)) {
qDebug() << "Process did not start.";
}
...
void SomeClass::onReadyRead() {
qDebug() << "Reading:" << process->readAllStdOutput();
}


My expected output would be:

Reading: yes 0
Reading: yes 1
...
Reading: yes 99


However i get no output at all.
And when i use QCoreApplication i get all the output but not through the signal/slot but directly in the console.

I dont understand because it works in another application that uses Qt 4.8.

My question is, is anyone experiencing the same problem or does anyone know how i can get the expected behaviour?

Answer

Well i solved my problem.

If the process is started with startDetached() it will not receive the signals from readyRead(), readyReadStandardOutput() and readyReadStandardError().

So just starting it with start() solved the problem.

However i noticed that if i start and do the while loop and prints in main() it will read everything at once even if it ends with \n. So i started the while loop in a thread and that problem was also solved. Everything prints as expected.

#include <QThread>

class Thread : public QThread 
{
    Q_OBJECT

public:
    explicit Thread(QObject *parent = 0) : QThread(parent) {}

protected:
    void run() {
        for (int i = 0; i < 100; i++) {
            std::cout << "yes" << i << std::endl;
            msleep(200);
        }
        exit(0);
    }
};

int main(int argc, char ** argv) {
    QCoreApplication app(argc,argv);
    Thread * t = new Thread();
    t->start();
    return app.exec();
}

TestP main.cpp

#include <QProcess>
#include <iostream>

class Controller : public QObject 
{
    Q_OBJECT
private:
    QProcess * process;

public:
    Controller(QObject *parent = 0) : 
        QObject(parent), process(new QProcess) {}

    void init(const QString &program) {
        connect(process,SIGNAL(readyRead()),this,SLOT(readStdOut()));
        connect(process,SIGNAL(started()),this,SLOT(onStarted()));
        connect(process,SIGNAL(finished(int)),this,SLOT(onFinished(int)));
        process->start(program);
    }

private slots:
    void readStdOut() {
        std::cout << "YES " << QString(process->readAllStandardOutput()).toUtf8().constData() << std::endl;
    }
    void onStarted(){
        std::cout << "Process started" << std::endl;
    }
    void onFinished(int) {
        std::cout << "Process finished: " << signal << std::endl;
    }
};

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
    Controller c;
    c.init("../Test/Test");
    return a.exec();
}
Comments