2011-09-17 3 views
7

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

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 
} 
+0

Is TestChild QProcess? и ввод - это QIODevice, а не подкласс? – Chris

+0

@Chris: Нет, TestChild - главный оконный объект дочернего процесса. В родительском процессе мы создаем дочерний, используя объект childProcess. Моя ошибка: 'input' - QFile, спасибо. –

ответ

0

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

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

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

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

+0

№ 'childProcess' - это объект управления в родительском процессе. Используя родительский процесс объекта childProcess', напечатайте строку в 'stdin' дочернего процесса (' TestParent :: writeToChildProcessOutput() '). И дочерний процесс должен прочитать эту строку из 'stdin'. Поэтому в дочернем процессе должен быть выдан сигнал 'readyRead()' объекта ввода QFile '(но не выдается сигнал 'readyRead()', 'TestChild :: readInput()' slot не вызывается). –

1

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

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

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

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

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

+0

Спасибо, попробуй QWinEventNotifier. Но проблема все еще существует: я запустил таймер, который каждый X ms пишет в лог-файл 'input.bytesAvailable()', и он всегда пишет '0'.Неверное использование 'bytesAvailable()' здесь? –

+0

'QSharedMemory' не пробовал. Но о 'QLocalSocket',' QLocalServer' (named pipe в Windows): мне все равно нужно обменивать имена труб (1 для каждого 'QLocalServer'). Есть ли другой простой метод для отправки имени трубы, кроме stdin/stdout? –

+1

1. Вы не можете заглядывать в stdin-буфер со стандартными библиотеками C/C++, поэтому было бы неудивительно, если Qt тоже этого не допустит. 2. Вы можете отправить имя канала в качестве аргументов подпроцесса. – alexisdm

6

Невозможно подключить порт в цикле событий 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(); 
+0

+1. Это полезно, спасибо. Разве вы не знаете, работает ли 'QProcess :: write' (stdin piping) в Windows? Другими словами: могу ли я написать stdin дочернего процесса? –

+0

Да, вы можете. Windows поддерживает трубопроводы. Просто обратите внимание на буферизацию. –

 Смежные вопросы

  • Нет связанных вопросов^_^