如何正确使用QProcess写入?

时间:2014-03-21 21:46:32

标签: c++ qt scanf qprocess

我需要一个程序来与依赖in-和的子进程通信 输出。问题是我显然无法正确使用QProcess

进一步向下的代码应创建一个QProcess,启动它并进入主while循环。在那里,它将子进程创建的所有输出打印到控制台,然后询问用户输入,然后通过write(...)传递给子进程。

最初我遇到了两个问题:

  1. 父进程无法读取子进程的printf
  2. 子流程中的
  3. scanf未收到通过write发送的字符串。
  4. 至于(1),我开始意识到这是由子进程'stdout的缓冲引起的问题。通过fflush(stdout)调用或关于其刷新行为的操作,可以轻松解决此问题。

    第二个问题是我无法解决的问题。调用write,甚至返回正确的发送字节数。但是,子进程不会继续执行,因为没有新数据写入其输出。 scanf似乎没有收到发送的数据。该程序给出的输出是:

    Subprocess should have started.
    124 bytes available!
    Attempting to read:
    Read: This is a simple demo application.
    Read: It solely reads stdin and echoes its contents.
    Read: Input exit to terminate.
    Read: ---------
    Awaiting user input: test
    Written 5 bytes
    No line to be read...
    Awaiting user input: 
    

    我被严重困在这里。 Google +沉重的想法让我失望了,我想把这个传递给你作为我最后的希望灯塔。如果我只是没有看到所有树木的森林,我的道歉。

    如果需要这些信息:我正在使用Qt5和clang编译器处理64位MacOS X.子进程代码在同一台机器上使用gcc编译。

    非常感谢您提前,

    NR

    主要码:

    int main() {
        // Command to execute the subprocess
        QString program = "./demo";
        QProcess sub;
        sub.start(program, QProcess::Unbuffered | QProcess::ReadWrite);
    
        // Check, whether the subprocess is starting correctly.
        if (!sub.waitForStarted()) {
            std::cout << "Subprocess could not be started!" << std::endl;
            sub.close();
            return 99;
        }
    
        std::cout << "Subprocess should have started." << std::endl;
    
        // Check, if the subprocess has written its starting message to the output.
        if (!sub.waitForReadyRead()) {
            std::cout << "No data available for reading. An error must have occurred." << std::endl;
            sub.close();
            return 99;
        }
    
        while (1) {
            // Try to read the subprocess' output
            if (!sub.canReadLine()) {
                std::cout << "No line to be read..." << std::endl;
            } else {
                std::cout << sub.bytesAvailable() << " bytes available!" << std::endl;
                std::cout << "Attempting to read..." << std::endl;
                while (sub.canReadLine()) {
                    QByteArray output = sub.readLine();
                    std::cout << "Read: " << output.data();
                }
            }
    
            std::cout << "Awaiting user input: ";
            std::string input;
            getline(std::cin, input);
    
            if (input.compare("exit") == 0) break;
    
            qint64 a = sub.write(input.c_str());
            qint64 b = sub.write("\n");
            sub.waitForBytesWritten();
            std::cout << "Written " << a + b << " bytes" << std::endl;
        }
    
        std::cout << "Terminating..." << std::endl;
        sub.close();
    }
    

    子流程码:

    int main() {
        printf("This is a simple demo application.\n");
        printf("It reads stdin and echoes its contents.\n");
        printf("Input \"exit\" to terminate.\n");
    
        while (1) {
            char str[256];
            printf("Input: ");
            fflush(stdout);
            scanf("%s", str);
    
            if (strcmp(str, "exit") == 0) return 0;
    
            printf("> %s\n", str);
        }
    }
    

    P.s:由于这是我关于SO的第一个问题,请告诉我是否有关于提问方式的问题。


    解决方案

    经过多次试验和试验后错误,我设法找到问题的解决方案。添加对waitForReadyRead()的调用会导致主进程等待,直到子进程写入新输出。工作代码是:

    ...
    sub.waitForBytesWritten();
    std::cout << "Written " << a + b << " bytes" << std::endl;
    // Wait for new output
    sub.waitForReadyRead();
    ...
    

    我仍然不知道为什么它会这样运作。我想它在某种程度上与getline()对阻塞waitForReadyRead()阻塞主要流程有关。对我而言,似乎getline()阻止了所有内容,包括子进程,导致scanf调用永远不会因竞争条件而被处理。

    如果理解的人可以放弃解释,那就太棒了。

    感谢您的帮助:)

    NR

1 个答案:

答案 0 :(得分:3)

这不起作用。您正在等待写入发送的字节,但您不是在等待回声。而是输入getline()函数,等待新用户输入。请记住,这里涉及两个过程,每个过程都可以延迟到任何程度。

除此之外,你应该考虑异步构建你的Qt应用程序(有一个事件循环)而不是尝试同步方法。这样你的Qt应用程序可以并行执行...例如读取输入或等待来自远程进程的输入,同时仍未被阻止并且能够接受用户输入。