Qt-调用外部程序


- 注意事项

假设有程序A、程序B和数据库D。B使用了数据库D(调用时使用了相对路径)且与D在同一目录下。
直接运行B时,能够正确访问数据库D,而当由A调用B时,B启动后却无法正常访问数据库D。出现这个问题的原因是被A调用的B相当于在A的目录下执行,即在A的同一目录下,B无法找到D。

要避免出现上述的问题有以下3个方法:
1. 在B中对数据库的访问使用绝对路径
2. 把A、B两个程序的执行目录合并(对于上述例子来说就是把A、B、D三个文件置于同一目录)
3. 把数据库D拷贝到A的同一目录下
推荐采用方法2,合并后的目录可作为一个整体,移动到任意目录下都能正常运行,同时也便于管理。



- 头文件

#include <QProcess>



- C缓冲机制

若希望获取QProcess调用的外部程序的标准输出,则须了解C语言的缓冲机制。

外部程序中的输出方法:
printf("...");
fprintf(stdout, "Hello STDOUT!\n");
fprintf(stderr, "Hello STDERR!\n");

缓冲方式:行缓冲、全缓冲

刷新缓冲区:
    fflush(stdout);
    fflush(stdin);
    fflush(stderr);



- 基本操作

// 获取外部程序标准输出
connect(&mProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(redFromStdOut()));
...
void FloodForecast::redFromStdOut()
{
    ui.textBrowse->append(mProcess.readAllStandardOutput());
}

// 获取外部程序标准错误
connect(&mProcess, SIGNAL(readyReadStandardError()), this, SLOT(redFromStdErr()));
...
void FloodForecast::redFromStdErr()
{
    ui.textBrowse->append(mProcess.readAllStandardError());
}

// 外部程序启动失败
connect(&mProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
...
void FloodForecast::processError(QProcess::ProcessError error)
{
    if(error==QProcess::FailedToStart)
    {
        ui.textBrowse->append("<font color=red>程序启动失败.</font>\r\n");
    }
}

// 外部程序结束
connect(&mProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
...
void FloodForecast::processFinished(int exitCode,QProcess::ExitStatus exitStatus)
{
    if(exitStatus == QProcess::CrashExit)
    {
        ui.textBrowse->append("<font color=red>程序异常终止.</font>\r\n");
    }
    else
    {
        ui.textBrowse->append("<font color=green>程序正常结束.</font>\r\n");
    }
}



- 调用方式

- 非阻塞方式
QProcess::startDetached("/opt/led 0 0");
调用的结果相当于在Shell中执行“/opt/led 0 0”,startDetached()方法不等led执行完,马上返回。该方法可用来调出系统终端(终端也是一个程序)。

- 阻塞方式
process->start("...");
外部程序启动后会阻塞原来的程序,直到外部程序退出,可结合线程解决此问题。这种方式的调用下,当原来的程序退出时,外部程序不受影响。



- 简单示例

#include <QProcess>

QProcess *cmdPing;
cmdPing = new QProcess(this);

connect(cmdPing, SIGNAL(readyRead()), this, SLOT(slot_Network_ReadCmdOutput()));
connect(cmdPing, SIGNAL(finished(int)), this, SLOT(slot_Network_CmdFinished(int)));

cmdPing->start("ping 192.168.0.124 -c 5");

void MainWindow::slot_Network_ReadCmdOutput()
{
    ui->tb_Network_Msg->insertPlainText(cmdPing->readAll());
    ui->tb_Network_Msg->verticalScrollBar()->setSliderPosition(
                ui->tb_Network_Msg->verticalScrollBar()->maximum());
}

void MainWindow::slot_Network_CmdFinished(int ret)
{
    // 当ping通时,ret = 0;当无法ping通时,ret != 0
    ...
    ui->pb_Network_Ping->setEnabled(true);
    ui->pb_Network_Udp->setEnabled(true);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值