开发者

Child process stdin doesn't get data, sent by parent process

Parent process write string "Message\n" to child process stdin. But child process don't receive it. Where is the problem in the code?

Qt 4.7.3

Parent process code:

// class TestParent : public QMainWindow
void TestParent::createChildProcess()
{
    childProcess = new QProcess( this );
    connect( ch开发者_如何学CildProcess, SIGNAL( started() ),
        this, SLOT( childProcessStarted() ) );
    connect( childProcess, SIGNAL( bytesWritten( qint64 ) ),
        this, SLOT( bytesWritten( qint64 ) ) );
    childProcess->start( "TestChild.exe", QProcess::ReadWrite );
}

void TestParent::writeToChildProcessOutput()
{
    qint64 bytesWritten = childProcess->write( "Message\n" );
    qDebug() << "ret: " << bytesWritten << " bytes written";
}

void TestParent::bytesWritten()
{
    qDebug() << "slot: " << bytesWritten << " bytes written";
}

Child process code:

// class TestChild : public QMainWindow
void TestChild::TestChild()
    // QFile TestChild::input;
    connect( &input, SIGNAL( readyRead() ),
        this, SLOT( readInput() ) );
    input.open( 0, QIODevice::ReadOnly ); // stdin
}

void TestChild::readInput()
{
    QString line;
    line.append( '(' );
    line.append( QString::number( input.bytesAvailable() ) )
    line.append( ')' );
    line.append( input.readAll() );

    list.append( line ); // add line to QListView
}


There is no way to portably hookup in the Qt event loop for stdin/stdout events. The following works on non-Windows platforms:

QSocketNotifier *n1 = new QSocketNotifier(0, QSocketNotifier::Read, this);
connect(n1, SIGNAL(activated(int)), this, SLOT(readInputChannel()));

QSocketNotifier *n2 = new QSocketNotifier(0, QSocketNotifier::Exception, this);
connect(n2, SIGNAL(activated(int)), this, SLOT(brokenInputChannel()));

"0" is the file descriptor (stdin).

I would use the above and then simulate something similar on Windows through a blocking thread that reads from stdin and generates a signal:

class StdinThread : public QThread
{
    Q_OBJECT
signals:
    void incomingData(QByteArray data);

public:
    void run(void)
    {
         char buf[1024];
         while (1)
         {
             int sz = fread(buf, 1, 1024, stdin);
             if (sz == 0)
                return;
             emit incomingData(QByteArray(buf, sz));
         }
     }
};

then, in the child process:

StdinThread *t = new StdinThread(this);
connect(t, SIGNAL(incomingData(QByteArray)), this, SLOT(processInputData(QByteArray)));
connect(t, SIGNAL(finished()), this, SLOT(brokenInputChannel()));
t->run();


The documentation says that QFile doesn't ever emit the signal readyRead().

But there is a private class: QWinEventNotifier in src/corelib/kernel/qwineventnotifier_p.h(link) that might work with GetStdHandle(STD_INPUT_HANDLE).

Another alternative is to wait for input with a blocking loop inside a dedicated thread:

QTextStream cin(stdin, QIODevice::ReadOnly);
while(!cin.atEnd())
{
   QString line = cin.readLine();
   emit newLine(line);
}

You could also look at other RPC methods (e.g. QLocalSocket, QSharedMemory).


What I believe you need to be doing is reading from the actual QProcess object (in this case childProcess, if I understand correctly).

Note that QProcess is actually a subclass of QIODevice, and also take special note of the following functions:

QProcess::setReadChannel()
QProcess::readAllStandardOutput()

You should be able to the readyRead() signal of your QProcess object instead of creating a QFile in an attempt to read stdin. The reason this doesn't work is that your QFile is associated with the same process as your MainWindow, and not your child process.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜