我正在尝试在Qt4中为我的基于tcl的工具创建一个GUI。为了填充小部件,我需要执行一些tcl命令。我读到了QProcess,我正在使用QProcess调用tcl脚本,然后从stdout获取它们的输出。 假设我在tcl中执行了3个命令,那么当我查询stdout时,我相信我应该看到3个输出对应于三个命令中的每一个,但是这并不是一致的。行为很脆弱。
正如你在main.cpp中看到的那样,我正在使用runTclCommand()函数执行多个命令,最后执行getData()函数来读取stdout。
main.cpp中:
#include <QApplication>
#include <QProcess>
#include <QDebug>
#include "Tclsh.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QByteArray out;
Tclsh *tcl = new Tclsh;
tcl->startTclsh();
tcl->runTclCommand("set ::tcl_interactive 1\n");
tcl->runTclCommand("set a 23\n");
tcl->runTclCommand("puts $a\n");
tcl->runTclCommand("set a 40\n");
tcl->runTclCommand("puts $a\n");
// out = idl->getData();
out = tcl->getData();
}
Tclsh.cpp:
#include <QProcessEnvironment>
#include <QProcess>
#include <QDebug>
#include "Tclsh.h"
void Tclsh::startTclsh() {
QString program = "/usr/bin/tclsh8.4";
this->setProcessChannelMode(QProcess::MergedChannels);
this->start(program);
if ( !this->waitForStarted()) {
qDebug()<<"ERROR Starting tclsh";
}
return;
}
void Tclsh::runTclCommand(const char *cmd) {
qDebug()<<"CMD:"<<cmd;
this->write(cmd);
if (!this->waitForBytesWritten()) {
qDebug()<<"Error in writing data";
}
}
QByteArray Tclsh::getData() {
if (!this->waitForReadyRead()) {
qDebug()<<"Error in reading stdout: Ready read signal is not emitted";
}
QByteArray data = this->readAllStandardOutput();
qDebug()<<"DATA:"<<data;
return data;
}
但是,有时我得到以下输出:
CMD: set ::tcl_interactive 1
CMD: set a 23
CMD: puts $a
CMD: set a 40
CMD: puts $a
DATA: "1
% 23
% 23
% "
有时这个:
CMD: set ::tcl_interactive 1
CMD: set a 23
CMD: puts $a
CMD: set a 40
CMD: puts $a
DATA: "1
"
我不明白为什么会这样。如果有人可以在我的方法中指出我的错误,我真的很感激。
谢谢, 新手
编辑:经过一些研究,这是我的想法
根据Qt手册,只要有新数据,就会发出readyRead信号(由@Frank Osterfeld指定,谢谢!)。它不会等待完整的输出数据可用(这是合理的,因为它不知道何时会发生)。因此我的方法并不好。我能做的是这样的事情: 开始这个过程 - &gt;等待进程完成 - &gt;读stdout
这将确保不会出现片状行为,因为当我正在阅读时,过程已经完成,因此无法获得新数据。
然而,在这个提出的方法中,我不清楚一件事:stdout是否特定于一个过程?我的意思是,可以发生那个应该从process1读取stdout输出的进程,可以从其他进程中获取其他stdout数据,这些进程恰好在process1的同时写入stdout吗?
谢谢, 新手
答案 0 :(得分:0)
我正在结束这个问题。不止一次从频道阅读似乎不是一个好主意。相反,我现在所做的就是一次性写出我想写的东西 - &gt;关闭写作频道 - &gt;然后读回来。这样我得到了一致的输出。