2011-09-17 20 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

されていますTestChild a QProcess?入力はQIODeviceであり、サブクラスではありませんか? – Chris

+0

@Chris:いいえ、TestChild - 子プロセスのメインウィンドウオブジェクトです。親プロセスでは、 'childProcess'オブジェクトを使って子プロセスを作成します。私の間違い: 'input'はQFileです、ありがとうございます。 –

答えて

0

私はあなたがやってする必要があると信じて、実際のQProcessオブジェクトから読んでいます(この場合、childProcess、私が正しく理解している場合)。

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

あなたが代わりにqfileにより作成のあなたのQProcessオブジェクトのreadyRead()信号ことができるようになります。QProcessは実際のQIODeviceのサブクラスであり、また、以下の機能の特別なメモをとって

注意stdinを読み込もうとしています。これがうまくいかない理由は、QFileがMainWindowと同じプロセスに関連付けられていて、子プロセスではないからです。

+0

いいえ、 'childProcess'は親プロセス内の制御オブジェクトです。 'childProcess'オブジェクトの親プロセスは、子プロセスの' stdin'( 'TestParent :: writeToChildProcessOutput()')に文字列を出力します。子プロセスは 'stdin'からその文字列を読み込むべきです。だから子プロセス 'readyRead()'の 'QFile input'オブジェクトのシグナルを送出する必要がありますが、' readyRead() 'シグナルは送出されません。' TestChild :: readInput() 'スロットは呼び出されません。 –

1

QFileは、readyRead()というシグナルを放出していません。

しかし、GetStdHandle(STD_INPUT_HANDLE)で動作するプライベートクラスQWinEventNotifiersrc/corelib/kernel/qwineventnotifier_p.h(link)にあります。

別の方法としては、専用のスレッド内のブロッキングループで入力を待つことです。

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

あなたはまた、他のRPCの方法(例えばQLocalSocketQSharedMemory)で見ることができます。

+0

ありがとう、QWinEventNotifierを試してみます。しかし、まだ問題が残っています。私は各X msがログファイル 'input.bytesAvailable()'に書き込むタイマーを起動していて、常に '0'を書き込みます。'bytesAvailable()'の使用法も正しくありませんか? –

+0

'QSharedMemory'は試しませんでした。しかし、 'QLocalSocket'、' QLocalServer'(Windowsの名前付きパイプ)について:私はまだパイプ名を交換しなければなりません(各 'QLocalServer'に対して1つ)。 stdin/stdout以外のパイプ名を送る簡単な方法はありますか? –

+1

1. C/C++の標準ライブラリでstdinバッファを見ることができないので、Qtがそれを許可しない場合は驚くことではありません。 2.サブプロセスの引数としてパイプ名を送信できます。 – alexisdm

6

stdin/stdoutイベントのQtイベントループに移植可能に接続する方法はありません。以下は非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配管)がWindows上で動作するかどうか分かりませんか?つまり、子プロセスの標準に書き込むことはできますか? –

+0

はいできます。 Windowsは配管をサポートしています。ちょうどバッファリングに注意してください。 –

関連する問題