2011-09-17 21 views
7

Ciąg do wpisywania procesu rodzica "Message\n" do procesu potomnego procesu potomnego. Ale proces potomny go nie otrzymuje. Gdzie jest problem z kodem?Stdin procesu potomnego nie otrzymuje danych, wysłanych przez proces macierzysty.

Qt 4.7.3

proces nadrzędny kod:

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

kod proces dziecka:

// 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 a QProcess? a dane wejściowe to QIODevice, a nie podklasa? – Chris

+0

@Chris: Nie, TestChild - główny obiekt okna procesu potomnego. W procesie nadrzędnym tworzymy obiekt potomny za pomocą obiektu 'childProcess'. Mój błąd: "input" to QFile, dziękuję. –

Odpowiedz

0

co wierzę trzeba robić czyta z obiektu rzeczywisty QProcess (w tym przypadku childProcess, jeśli rozumiem poprawnie).

Zauważ, że QProcess jest faktycznie podklasa QIODevice, a także zwrócić szczególną uwagę na następujące funkcje:

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

Powinieneś być w stanie do readyRead() sygnału Twojego obiektu QProcess zamiast tworzenia QFile próbując odczytać stdin. Powodem, dla którego to nie działa, jest to, że Twój plik QFile jest powiązany z tym samym procesem, co Twój MainWindow, a nie proces twojego dziecka.

+0

Nie "childProcess" jest obiektem kontrolnym w procesie nadrzędnym. Użycie łańcucha macierzystego obiektu childProcess dla procesu nadrzędnego 'stdin' procesu potomnego (' TestParent :: writeToChildProcessOutput() '). Proces potomny powinien odczytać ten ciąg z 'stdin'. Więc w procesie potomnym powinien być emitowany sygnał 'readyRead()' obiektu 'QFile input' (ale nie ma emitowanego sygnału' readyRead() ',' 'TestChild :: readInput()' nie jest wywoływany). –

1

Dokumentacja mówi, że QFile nigdy nie wysyła sygnału readyRead().

Ale istnieje klasa prywatna: QWinEventNotifier w src/corelib/kernel/qwineventnotifier_p.h(link), która może działać z GetStdHandle(STD_INPUT_HANDLE).

Inną alternatywą jest poczekać na wejściu z pętlą blokującej wewnątrz specjalnego gwintu:

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

Można też, w innych metodach RPC (np QLocalSocket, QSharedMemory).

+0

Dzięki, spróbuję QWinEventNotifier. Ale problem nadal istnieje: Uruchomiłem timer, który każdy X ms zapisuje do pliku dziennika 'input.bytesAvailable()', i zawsze zapisuje '0'.Czy użycie "bytesAvailable()" jest tu niepoprawne? –

+0

'QSharedMemory' nie próbował. Ale o 'QLocalSocket',' QLocalServer' (nazwanym potoku w Windows): Nadal muszę wymieniać nazwy potoków (1 dla każdego 'QLocalServer'). Czy istnieje inna prosta metoda wysyłania nazwy potoku, inna niż stdin/stdout? –

+1

1. Nie można zajrzeć do bufora stdin ze standardowymi bibliotekami C/C++, więc nie byłoby zaskoczeniem, gdyby Qt na to nie zezwalał. 2. Możesz wysłać nazwę potoku jako argumenty podprocesu. – alexisdm

6

Nie ma sposobu na przenośne podłączenie pętli zdarzeń Qt dla zdarzeń stdin/stdout. Następujące działa na platformach innych niż 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" jest deskryptorem pliku (stdin).

użyłbym powyższą a następnie symulować coś podobnego w systemie Windows za pomocą gwintu blokującej, który czyta ze standardowego wejścia i generuje sygnał:

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

następnie w procesie dziecko:

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. To pomocne, dzięki. Czy nie wiesz, czy 'QProcess :: write' (stdin piping) działa w systemie Windows? Innymi słowy: czy mogę zapisać na stdin procesu potomnego? –

+0

Tak, możesz. Windows obsługuje rurociągi. Zwróć uwagę na buforowanie. –

Powiązane problemy