Дочерний процесс stdin не получает данные, отправленные родительским процессом - PullRequest
7 голосов
/ 18 сентября 2011

Родительский процесс записывает строку "Message\n" в стандартный процесс дочернего процесса. Но дочерний процесс не получает его. Где проблема в коде?

Qt 4.7.3

Код родительского процесса:

// class TestParent : public QMainWindow
void TestParent::createChildProcess()
{
    childProcess = new QProcess( this );
    connect( childProcess, 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";
}

Код дочернего процесса:

// 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
}

Ответы [ 3 ]

6 голосов
/ 28 сентября 2011

Нет способа портативного подключения в цикле событий Qt для событий stdin / stdout.Следующее работает на платформах, отличных от Windows:

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" - это дескриптор файла (stdin).

Я бы использовал вышеизложенное и затем симулировал что-то похожее на Windows с помощью блокировкипоток, который читает из стандартного ввода и генерирует сигнал:

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));
         }
     }
};

затем, в дочернем процессе:

StdinThread *t = new StdinThread(this);
connect(t, SIGNAL(incomingData(QByteArray)), this, SLOT(processInputData(QByteArray)));
connect(t, SIGNAL(finished()), this, SLOT(brokenInputChannel()));
t->run();
1 голос
/ 18 сентября 2011

В документации сказано, что QFile никогда не излучает сигнал readyRead().

Но есть закрытый класс: QWinEventNotifier в src/corelib/kernel/qwineventnotifier_p.h (ссылка) , который может работать с GetStdHandle(STD_INPUT_HANDLE).

Другой альтернативой является ожидание ввода с помощью блокирующего цикла внутри выделенного потока:

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

Вы также можете посмотреть другие методы RPC (например, QLocalSocket, QSharedMemory).

0 голосов
/ 18 сентября 2011

Я полагаю, что вам нужно сделать чтение из реального объекта QProcess (в данном случае childProcess, если я правильно понимаю).

Обратите внимание, что QProcess фактически является подклассом QIODevice, а также обратите особое внимание на следующие функции:

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

Вы должны быть в состоянии сигнала readyRead () вашего объекта QProcess вместо создания QFile при попытке чтения стандартного ввода. Причина, по которой это не работает, заключается в том, что ваш QFile связан с тем же процессом, что и ваше MainWindow, а не с вашим дочерним процессом.

...