通过stdin/stdout和qdatastream与Qprocess进行通信
Communicating with QProcess via stdin/stdout and QDataStream
我正在尝试编写一个可以产生子过程并通过标准输出/输入与之通信的应用程序。只是为了掌握它,我尝试编写一个简单的应用程序,该应用程序可以向子过程发送消息,而子过程会接收它并将其发送回。坦率地说,经过荒谬的反复试验,我设法向子过程收到了一条消息,但我不知道如何将其发送回去。
这是我的尝试:
#include <QApplication>
#include <QDataStream>
#include <QFile>
#include <QDebug>
#include <QProcess>
#include <QThread>
#define dumpval(x) qDebug()<<#x<<'='<<x
void slave()
{
QApplication::setApplicationName("slave");
qSetMessagePattern("%{appname}: %{message}");
qDebug()<<"started";
QFile input;
QFile output;
dumpval(input.open(stdin, QFile::ReadOnly));
dumpval(output.open(stdout, QFile::WriteOnly));
QObject::connect(&output, &QIODevice::bytesWritten, [](int bytesWritten){dumpval(bytesWritten);});
QDataStream inputStream(&input);
QDataStream outputStream(&output);
QByteArray data;
while (true){
inputStream>>data;
dumpval(data);
if (!data.isEmpty()) break;
inputStream.resetStatus();
QThread::sleep(1);
}
dumpval(output.isWritable());
outputStream<<data;
dumpval(output.waitForBytesWritten(-1));
qDebug()<<"data written";
qDebug()<<"stopped";
}
void master(QString path)
{
QApplication::setApplicationName("master");
qSetMessagePattern("%{appname}: %{message}");
qDebug()<<"started";
QProcess p;
QObject::connect(&p, &QIODevice::bytesWritten, [](int bytesWritten){dumpval(bytesWritten);});
p.setProgram(path);
p.setArguments({"slave"});
p.setProcessChannelMode(QProcess::ForwardedErrorChannel);
p.start();
p.waitForStarted();
QDataStream stream(&p);
QByteArray data = "this is a test";
stream<<data;
dumpval(p.waitForBytesWritten(-1));
data.clear();
while (true){
stream>>data;
dumpval(data);
if (!data.isEmpty()) break;
stream.resetStatus();
QThread::sleep(1);
}
qDebug()<<"stopped";
}
int main(int argc, char** argv)
{
if (argc == 1) master(argv[0]);
else slave();
}
这是此代码的输出:
master: started
master: bytesWritten = 18
master: p.waitForBytesWritten(-1) = true
master: data = ""
slave: started
slave: input.open(stdin, QFile::ReadOnly) = true
slave: output.open(stdout, QFile::WriteOnly) = true
slave: data = "this is a test"
slave: output.isWritable() = true
slave: output.waitForBytesWritten(-1) = false
slave: data written
slave: stopped
master: data = ""
master: data = ""
master: data = ""
master: data = ""
master: data = ""
master: data = ""
^C
我在做什么错?
QFile
不能实现异步接口。读取和写入正在阻止,waitForXxx
方法是无op的。
请参阅此问题,以了解如何实现非阻滞控制台I/O,您是否希望这样做。
由于QFile
正在阻止,因此slave()
不需要检查状态的循环。
您使用QProcess
使用其阻止API,因此不需要使用其信号。您还假设读取将返回完整的数据。控制台I/O是面向流的,而不是面向消息的,因此您必须使用QDataStream
交易来确保读取在原子上成功。readyRead
指示仅表示有些数据可用。它可能只是一个字节。
如果您想使用一种非阻止状态的方法来处理QProcess
和类似的通信,请参见此答案。
请注意,使用argc[0]
作为从属开始自我启动是不可靠的。改用QCoreApplication::applicationFilePath()
。
下面的示例有效,并产生以下输出:
master: started
slave: started
slave: input.open(stdin, QFile::ReadOnly) = true
slave: output.open(stdout, QFile::WriteOnly) = true
slave: data = "this is a testx00"
slave: data = ""
slave: inputStream.status() = 0
slave: stopped
master: data = "this is a testx00"
master: data = ""
master: stopped
// https://github.com/KubaO/stackoverflown/tree/master/questions/process-echo-43523282
#include <QtCore>
#define dumpval(x) qDebug()<<#x<<'='<<x
void slave()
{
QCoreApplication::setApplicationName("slave");
qDebug()<<"started";
QFile input, output;
QDataStream inputStream{&input}, outputStream{&output};
dumpval(input.open(stdin, QFile::ReadOnly));
dumpval(output.open(stdout, QFile::WriteOnly));
QByteArray data;
do {
inputStream >> data;
outputStream << data;
dumpval(data);
} while (inputStream.status() == QDataStream::Ok && !data.isEmpty());
dumpval(inputStream.status());
}
void master()
{
QCoreApplication::setApplicationName("master");
qDebug()<<"started";
QProcess p;
p.setProgram(QCoreApplication::applicationFilePath());
p.setArguments({"slave"});
p.setProcessChannelMode(QProcess::ForwardedErrorChannel);
p.start();
p.waitForStarted();
QDataStream stream(&p);
QByteArray data;
stream << "this is a test" << QByteArray{};
while (true) {
stream.startTransaction();
stream >> data;
if (stream.commitTransaction()) {
dumpval(data);
if (data.isEmpty())
break;
} else
p.waitForReadyRead();
}
p.waitForFinished();
}
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
qSetMessagePattern("%{appname}: %{message}");
if (app.arguments().size() < 2) master(); else slave();
qDebug() << "stopped";
}
相关文章:
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 使用QProcess执行命令,并将结果存储在QStringList中
- 是否可以使用winusb同时与多个相同的usb设备进行通信
- 混淆了如何使用IDL与Ethovision进行通信
- C++ Boost::asio串行通信与Arduino无法写入
- 终止 QProcess 不会终止子进程
- 我是否需要包含隐式使用/与 WindowsAPI 通信"Windows.h"?
- 通过TCP的PvP通信问题
- 在 Qt(C++) 中使用 QProcess 解压缩 - 提取目录问题
- C++一个线程如何正确通信其任务已完成?
- 如何将 Firebase 与基于 Linux 的客户端应用配合使用,以便与服务器进行双向消息通信
- 当QProcess需要用户使用Qt输入时,如何阅读
- 删除功能不适用于串行通信后多个循环中的多个实例
- 网站和C++程序在同一台 Linux PC 上的通信
- 通过插槽和信号在不同线程中的两个qt对象之间进行通信
- 与QProcess Python程序通信
- 通过stdin/stdout和qdatastream与Qprocess进行通信
- 与 QProcess 和 VS C++的实时通信出现问题
- 从QThread与QProcess通信
- (Qt-QProcess)与控制台应用程序的通信