如何正确使用QProcess写入?

NRi*_*rer 5 c++ qt scanf qprocess

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

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

最初我遇到了两个问题:

  1. printf"子进程的s不能由父进程读取.
  2. scanf在子进程中没有收到通过发送的字符串write.

至于(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: 
Run Code Online (Sandbox Code Playgroud)

我被严重困在这里.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();
}
Run Code Online (Sandbox Code Playgroud)

子码:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Ps:因为这是关于SO的第一个问题,请告诉我是否有关于提问方式的问题.


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

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

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

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

谢谢您的帮助 :)

NR

Sil*_*cer 3

这是行不通的。您正在等待写入发送的字节,但没有等待回显。相反,您将进入 getline() 函数等待新的用户输入。请记住,这里涉及两个过程,每个过程都可以延迟到任意程度。

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