首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何正确使用QProcess写?

如何正确使用QProcess写?
EN

Stack Overflow用户
提问于 2014-03-21 21:46:32
回答 1查看 6.3K关注 0票数 5

我需要一个程序来与依赖于内部和输出的子进程进行通信。问题是我显然不能正确地使用QProcess

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

最初,我在这个场景中出现了两个问题:

  1. 父进程无法读取子进程的printf
  2. 子进程中的scanf没有接收到通过write发送的字符串。

至于(1),我意识到这是子进程的stdout缓冲造成的一个问题。这个问题可以很容易地通过fflush(stdout)调用或操作来解决。

第二个问题是那个我不能把头绕过去的问题。write被调用,甚至返回正确的发送字节数。但是,子进程没有继续其扩展,因为没有向其输出写入新的数据。scanf似乎没有接收到发送的数据。该程序提供的输出如下:

代码语言:javascript
运行
复制
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: 

我真的被困在这里了。谷歌+沉重的思想失败在我身上,我想把这作为我最后的希望灯塔传递给你。如果我只是没能看到所有树木的森林,我很抱歉。

如果需要这些信息的话:我正在使用Qt5和clang编译器开发64位的Qt5 X。子进程代码与gcc在同一台机器上编译。

提前谢谢你,

天然橡胶

主要代码:

代码语言:javascript
运行
复制
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();
}

Subprocess-Code:

代码语言:javascript
运行
复制
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);
    }
}

记者:既然这是我的第一个问题,请告诉我问的方式是否有问题。

溶液

经过多次试验和错误之后,我设法想出了解决这个问题的办法。添加对waitForReadyRead()的调用将导致主进程等待子进程写入新的输出。工作守则是:

代码语言:javascript
运行
复制
...
sub.waitForBytesWritten();
std::cout << "Written " << a + b << " bytes" << std::endl;
// Wait for new output
sub.waitForReadyRead();
...

我还是不知道为什么会这样。我猜想这与getline()对主进程的阻塞和waitForReadyRead()的阻塞有关。在我看来,似乎getline()阻塞了所有东西,包括子进程,导致scanf调用永远不会因为竞争条件而被处理。

如果有人能理解我的解释,那就太好了。

(谢谢你的帮助:)

天然橡胶

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-21 22:52:54

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

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22570102

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档