【问题标题】:Qt: How to catch an error with system call?Qt:如何通过系统调用捕获错误?
【发布时间】:2013-12-30 12:23:33
【问题描述】:

我正在构建一个 GUI 应用程序,我在其中执行系统调用并调用 gnuplot 来运行脚本。现在我想构建一条错误消息,说明何时出现问题(例如 gnuplot 未安装或路径错误)。

所以一直想着放一个QMessageBox,但是不知道怎么检查系统调用是否成功。

if(//System call didn't work)
{
    QMessageBox msgBox;
    msgBox.setWindowTitle("Error");
    msgBox.setIcon(QMessageBox::Critical);
    msgBox.setText("GNUPLOT was not installed");
    msgBox.exec();
}

我的系统调用如下所示:

system(gnuplot script.txt);

有什么建议吗?

【问题讨论】:

    标签: c++ qt qprocess qtcore qiodevice


    【解决方案1】:

    您应该使用QProcess 而不是低级系统调用,因为它是 Qt 代码库中的一个很好的抽象。否则,您最终将处理特定于平台的位。 QProcess 已经为您解决了这个问题。如果你碰巧对阻塞方法没问题,也就是。同步,你可以在下面写类似的代码。

    QProcess process;
    
    process1.start("gnuplot arg1 arg2 etc");
    
    // Wait for it to start
    if(!process.waitForStarted())
        return 0;
    
    bool retval = false;
    QByteArray buffer;
    while ((retval = process.waitForFinished()));
        buffer.append(process.readAll());
    
    if (!retval) {
        qDebug() << "Process 2 error:" << process.errorString();
        msgBox.setText(buffer);
        return 1;
    }
    

    如果您不想在您的 gnuplot 脚本运行时阻塞,您可以将一个插槽或简单的 lambda 与 C++11 及更高版本连接到 readyRead() 信号。当然,您还需要连接到error() 信号。在 C++11 之前的环境中没有 lambda 的代码看起来像这样:

    GnuPlotReader::GnuPlotReader(QQProcess *process, QObject *parent)
        : QObject(parent)
        , m_process(process)
        , m_standardOutput(stdout)
    {
        connect(m_process, SIGNAL(readyRead()), SLOT(handleReadyRead()));
        connect(m_process, SIGNAL(error(QProcess::ProcessError)), SLOT(handleError(QProcess::ProcessError)));
        connect(&m_timer, SIGNAL(timeout()), SLOT(handleTimeout()));
    
        m_timer.start(5000);
    }
    
    GnuPlotReader::~GnuPlotReader()
    {
    }
    
    void GnuPlotReader::handleReadyRead()
    {
        m_readData = m_process->readAll();
    
        if (!m_timer.isActive())
            m_timer.start(5000);
    }
    
    void GnuPlotReader::handleTimeout()
    {
        if (m_readData.isEmpty()) {
            m_standardOutput << QObject::tr("No data was currently available for reading from gnuplot") << endl;
        } else {
            m_standardOutput << QObject::tr("GnuPlot successfully run")<< endl;
        }
    
    }
    
    void GnuPlotReader::handleError(QProcess::ProcessError processError)
    {
        if (processError == QProcess::ReadError) {
            m_standardOutput << QObject::tr("An I/O error occurred while reading the data, error: %2").arg(m_process->errorString()) << endl;
            messageBox.setText(m_readData);
        }
    }
    

    【讨论】:

    • 我还建议处理异步 API,而不是像 waitForStarted 这样阻塞事件循环的函数。
    • @fasked:两者都是有效的用例,因此都提到了。
    • 我尝试使用 QProcess 没有成功,我正在再次尝试,但它似乎并没有那样工作。 stackoverflow.com/questions/20841116 我解释了我想要做的确切事情以及到目前为止我尝试过的事情
    • 那是因为您没有指定 local gnuplot 安装的完整路径。当然,如果它不在 PATH 中,则需要正确的相对或绝对路径。这与 shell 操作没有什么不同。 :)
    猜你喜欢
    • 2011-10-24
    • 2013-12-24
    • 1970-01-01
    • 1970-01-01
    • 2012-07-08
    • 2021-07-20
    • 2021-08-27
    • 1970-01-01
    • 2023-03-05
    相关资源
    最近更新 更多