Qt QProcess 进程间通信读写数据通信

本文介绍了如何使用Qt的QProcess  进行程序开发,包括启动进程间通信、设置环境变量、通用方法;方便在日常开发中使用;

1.使用Qt进行程序开发,可以通过QProcess类用于启动外部程序并与其进行通信.;

进程A(例如主程序)创建了一个QProcess B,这个B就称为A的子进程,而A称为B的父进程。

1.1. 运行进程 

可以使用 Start  or Open

要启动进程,需要运行的程序的名称和命令行参数作为参数传递给start()。参数以QStringList形式提供。
start()方法原型:

void start(const QString &program, const QStringList &arguments, OpenMode mode = ReadWrite)
void start(const QString &command, OpenMode mode = ReadWrite)

也可以使用setProgram()setArguments()设置要运行的程序,然后调用start()open()
以下是setProgram()setArguments()open()函数原型:

bool open(OpenMode mode = ReadWrite) Q_DECL_OVERRIDE;QString program() const;void setProgram(const QString &program);QStringList arguments() const;void setArguments(const QStringList & arguments);

1.2 环境运行设置

因为有一些程序会有依赖,所以需要设备运行环境:

通过调用setProcessEnvironment()为进程设置环境变量。

要设置工作目录,请调用setWorkingDirectory()。默认情况下,进程在调用进程的当前工作目录中运行

原型:

void QProcess::setProcessEnvironment(const QProcessEnvironment &environment)

样例:

  QProcess process;QProcessEnvironment env = QProcessEnvironment::systemEnvironment();env.insert("PATH", "E:\\Program"); // Add an environment variableprocess.setProcessEnvironment(env);process.start("app.exe");

1.3. 进程间通信
1.3.1关于父进程读写子进程的数据,主要是用到

子进程接收到了父进程数据,两个信号会发射出来:
void readyReadStandardError()
void readyReadStandardOutput()

父进程通过上面这两个信号,判断读取子进程发来的消息;

QByteArray QProcess::readAllStandardError()
QByteArray QProcess::readAllStandardOutput()

QProcess::write()发出信息

1.3.2 关于子进程读写父进程的数据,主要是用到

Windows中:需要开启一个线程来管理stdin的文件变化,这个需要使用Windows API函数
linux中:使用QSocketNotifier 监听 stdin文件,当改文件有变化是,读取信息

 

ReadFile(hStdinDup,chbuf,sizeof(chbuf),&dwRead,NULL);// get  hstdinDup handle data

这个是阻塞函数,类似控制台程序中的cin >> data,或者gets()。

因此需要开启一个线程来管理stdin的文件变化(函数中有涉及到while阻塞,一直检测标准输入通道stdin是否有可读取的信息,因此另开线程),在pro文件中添加:QT +=concurrent。实例代码如下:

QFuture<void> fu=QtConcurrent::run(this,&Widget::readStdin);// open a threadvoid Widget::readStdin()
{bool ok=true;char chbuf[1024]; DWORD dwRead; HANDLE hStdinDup;//HANDLE  const HANDLE hStdin=GetStdHandle(STD_INPUT_HANDLE);//GetStdHandle if(hStdin==INVALID_HANDLE_VALUE)// return;DuplicateHandle(GetCurrentProcess(),hStdin,GetCurrentProcess(),&hStdinDup,0,false,DUPLICATE_SAME_ACCESS); CloseHandle(hStdin);while(ok){ok=ReadFile(hStdinDup,chbuf,sizeof(chbuf),&dwRead,NULL);//emit sig_log(QLatin1String("ok is:")+QString::number(ok));if(ok &&dwRead!=0){emit sig_receivedCommand(QString::fromUtf8(chbuf,dwRead));}}}


 linux平台:QFile来读取标准输入

QProcess子进程通过QFile来读取标准输入来接收父进程信息。通过QFile绑定QSocketNotifier来接收标准输入的实时信号,因为QSocketNotifier的activated信号可以通过标准输入是否有消息实时触发。

QProcess子进程通过QFile绑定标准输出stdout来发送消息给父进程。
注意:子进程读取信息不能通过QFile的readline等接口读取父进程信息,因为QFile他会读取标准输入的所有信息,并且不到长度就没有返回
 

m_file.open(stdin, QFile::ReadOnly); //stdin=0if (m_file.isOpen()){m_clientsocket = new QSocketNotifier(m_file.handle(), QSocketNotifier::Read,this);connect(m_clientsocket,SIGNAL(activated(int)),this,SLOT(slotreaddata(int)));}void MainWindow::slotreaddata(int fd){if(fd != m_file.handle() )return;    char buf[128] = {0};read(fd,buf,sizeof(buf));      m_readedit->append(QString::fromUtf8("rev msg:%1").arg(buf));
}

2. 程序样例:

主进程
 

#include "mainwindow.h"
#include "ui_mainwindow.h"#include <QDebug>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);
}MainWindow::~MainWindow()
{if(m_pProcess){m_pProcess->close();}delete ui;
}void MainWindow::on_btn_invokingClient_clicked()
{if(!m_pProcess){m_pProcess = new QProcess(this);// 完成时调用connect(m_pProcess, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this, [=](int exitCode, QProcess::ExitStatus exitStatus){Q_UNUSED(exitCode)Q_UNUSED(exitStatus)});// 进程错误时触发connect(m_pProcess, static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::error), this, [=](QProcess::ProcessError error1){Q_UNUSED(error1)});// 读取connect(m_pProcess, &QProcess::readyRead, this, [this](){if(!m_pProcess)return;QString strOutput = QString("[客户端发送输出 ] %1").arg(QString(m_pProcess->readAllStandardOutput()));ui->textBrowser->append(strOutput);});// 读取标准错误信息connect(m_pProcess, &QProcess::readyReadStandardError, this, [=](){QString strError = QString("[客户端发送错误 ] %1").arg(QString(m_pProcess->readAllStandardError()));ui->textBrowser->append(strError);});// 状态改变时触发connect(m_pProcess, &QProcess::stateChanged, this, [=](QProcess::ProcessState state){Q_UNUSED(state)});}m_pProcess->start("G:/workspace/Qt_process-invoke-client/build-client-Desktop_Qt_5_12_4_MSVC2017_64bit-Debug/debug/client.exe");
}void MainWindow::on_btn_sendValueToClient_clicked()
{if(!m_pProcess)return;// 可输中文m_pProcess->write(ui->lineEdit->text().toUtf8());
}

子进程:

#include "mainwindow.h"
#include "ui_mainwindow.h"#include <QDebug>
#include <QFile>
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <QFuture>
#include <QtConcurrent/QtConcurrent>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);setWindowTitle("client");QFuture<void> f1 = QtConcurrent::run(this, &MainWindow::readstdin);connect(this,&MainWindow::sig_receivedCommand, this, [&](QString text){ui->textBrowser->append("[读取标准输入 ] "+ text);});connect(this, &MainWindow::sig_log, this, &MainWindow::slot_print);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_btn_sendOutputToInvoker_clicked()
{QString text = ui->lineEdit->text();if(text.isEmpty()) return;
#if 0QFile fileout;if(fileout.open(stdout,QIODevice::WriteOnly)){fileout.write(text.toStdString().c_str());}else{printErr("open fail");}fileout.close();
#elsestd::cout << text.toStdString() << std::endl;
#endif
}void MainWindow::printErr(const QString &errText)
{QFile fileerr;if(fileerr.open(stderr,QIODevice::WriteOnly)){fileerr.write(errText.toStdString().c_str());}fileerr.close();
}void MainWindow::on_btn_sendErrToInvoker_clicked()
{QString text = ui->lineEdit->text();if(text.isEmpty()) return;
#if 1QFile fileerr;if(fileerr.open(stderr,QIODevice::WriteOnly)){fileerr.write(text.toStdString().c_str());}fileerr.close();
#elsestd::cerr << text.toStdString() << std::endl;
#endif
}void MainWindow::slot_print(const QString &text)
{ui->textBrowser->append("[读取标准输入 ] "+ text);
}
void MainWindow::readstdin()
{bool ok = true;char chBuf[4096];DWORD dwRead;HANDLE hStdinDup;const HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);if (hStdin == INVALID_HANDLE_VALUE)return;DuplicateHandle(GetCurrentProcess(), hStdin,GetCurrentProcess(), &hStdinDup,0, false, DUPLICATE_SAME_ACCESS);CloseHandle(hStdin);while (ok) {ok = ReadFile(hStdinDup, chBuf, sizeof(chBuf), &dwRead, NULL);// emit sig_log(QLatin1String("ok is:")+QString::number(ok));if (ok && dwRead != 0){emit sig_receivedCommand(QString::fromUtf8(chBuf, dwRead));}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/381502.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Grafana :利用Explore方式实现多条件查询

背景 日志统一推送到Grafana上管理。所以&#xff0c;有了在Grafana上进行日志搜索的需求&#xff0c;而进行日志搜索通常需要多条件组合。 解决方案 通过Grafana的Explore的方式实现多条件查询。 直接看操作步骤&#xff1a; 在主页搜索框中输入“Explore” 进入这个界面…

Linux下开放指定端口

比如需要开放82端口&#xff1a; #查询是否开通 firewall-cmd --query-port82/tcp#开放端口82 firewall-cmd --zonepublic --add-port82/tcp --permanent#重新加载防火墙 firewall-cmd --reload

[计算机网络] VPN技术

1. 概述 虚拟专用网络&#xff08;VPN&#xff09;技术利用互联网服务提供商&#xff08;ISP&#xff09;和网络服务提供商&#xff08;NSP&#xff09;的网络基础设备&#xff0c;在公用网络中建立专用的数据通信通道。VPN的主要优点包括节约成本和提供安全保障。 优点&#…

Android RSA 加解密

文章目录 一、RSA简介二、RSA 原理介绍三、RSA 秘钥对生成1. 密钥对生成2. 获取公钥3. 获取私钥 四、PublicKey 和PrivateKey 的保存1. 获取公钥十六进制字符串1. 获取私钥十六进制字符串 五、PublicKey 和 PrivateKey 加载1. 加载公钥2. 加载私钥 六、 RSA加解密1. RSA 支持三…

[HTML]一文掌握

背景知识 主流浏览器 浏览器是展示和运行网页的平台&#xff0c; 常见的五大浏览器有 IE浏览器、火狐浏览器&#xff08;Firefox&#xff09;、谷歌浏览器&#xff08;Chrome&#xff09;、Safari浏览器、欧朋浏览器&#xff08;Opera&#xff09; 渲染引擎 浏览器解析代码渲…

Go语言 Import导入

本文主要介绍Go语言import导入使用时注意事项和功能实现示例。 目录 Import 创建功能文件夹 加法 减法 主函数 优化导入的包名 .引入方法 总结 Import 创建功能文件夹 做一个计算器来演示&#xff0c;首先创建test文件夹。 加法 在test文件夹中创建add文件夹&#xff…

高性能分布式IO系统BL205 OPC UA耦合器

边缘计算是指在网络的边缘位置进行数据处理和分析&#xff0c;而不是将所有数据都传送到云端或中心服务器&#xff0c;这样可以减少延迟、降低带宽需求、提高响应速度并增强数据安全性。 钡铼BL205耦合器就内置边缘计算功能&#xff0c;它不依赖上位机和云平台&#xff0c;就能…

大语言模型-Transformer-Attention Is All You Need

一、背景信息&#xff1a; Transformer是一种由谷歌在2017年提出的深度学习模型。 主要用于自然语言处理&#xff08;NLP&#xff09;任务&#xff0c;特别是序列到序列&#xff08;Sequence-to-Sequence&#xff09;的学习问题&#xff0c;如机器翻译、文本生成等。Transfor…

上位机图像处理和嵌入式模块部署(香橙派AI Pro开发板试用)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 和工控机相比较,linux嵌入式开发板使用上面方便很多、也容易很多。很多的第三方库都可以通过yum、apt-get这样的方法直接下载到,不需要自己通过源代码重新进行编译、安装。因为自…

单链表<数据结构 C版>

目录 概念 链表的单个结点 链表的打印操作 新结点的申请 尾部插入 头部插入 尾部删除 头部删除 查找 在指定位置之前插入数据 在任意位置之后插入数据 测试运行一下&#xff1a; 删除pos结点 删除pos之后结点 销毁链表 概念 单链表是一种在物理存储结构上非连续、非顺序…

【C语言】 利用栈完成十进制转二进制(分文件编译,堆区申请空间malloc)

利用栈先进后出的特性&#xff0c;在函数内部&#xff0c;进行除二取余的操作&#xff0c;把每次的余数存入栈内&#xff0c;最后输出刚好就是逆序输出&#xff0c;为二进制数 学习过程中&#xff0c;对存储栈进行堆区的内存申请时候&#xff0c;并不是很熟练&#xff0c;一开始…

Linux操作系统的有关常用的命令

1.linux系统的概述 1.1 什么是Linux系统? Linux&#xff0c;全称GNU/Linux&#xff0c;是一种免费使用和自由传播的类UNIX操作系统&#xff0c;其内核由林纳斯本纳第克特托瓦 兹&#xff08;Linus Benedict Torvalds&#xff09;于1991年10月5日首次发布&#xff0c;它主要受…

Unity 调试死循环程序

如果游戏出现死循环如何调试呢。 测试脚本 我们来做一个测试。 首先写一个死循环代码&#xff1a; using System.Collections; using System.Collections.Generic; using UnityEngine;public class dead : MonoBehaviour {void Start(){while (true){int a 1;}}}Unity对象设…

matlab simulink气隙局部放电仿真技术研究

1、内容简介 略 87-可以交流、咨询、答疑 2、内容说明 略 为了解决目前国内外局部放电仿真方法难以计算气隙局部放电暂态过程的问题 , 利用 MATLAB (SIMULINK ) 的公共模块库和电力系统专业模块库 , 根据单气隙局部放电仿真物理模型 , 构造了气隙局部放 电仿真计算的电…

C++_单例模式

目录 1、饿汉方式实现单例 2、懒汉方式实现单例 3、单例模式的总结 结语 前言&#xff1a; 在C中有许多设计模式&#xff0c;单例模式就是其中的一种&#xff0c;该模式主要针对类而设计&#xff0c;确保在一个进程下该类只能实例化出一个对象&#xff0c;因此名为单例。而…

新能源风机视觉数据集

需要的同学私信联系&#xff0c;推荐关注上面图片右下角平台自取下载。 全球风电装机的快速扩张推高了风电场运维巡检的需求&#xff0c;原本高度依赖人力的风电运维巡检工作正因智能化、数字化、无人化技术的应用出现变革。AI智慧风机检测可以促进风电领域运维检测新技术产、…

操作系统——文件管理

1&#xff09;什么是文件&#xff1f; 2&#xff09;单个文件的逻辑结构和物理结果之间是否存在制约关系&#xff1f; 本节内容较为抽象&#xff0c;本节要注意区分文件的逻辑结构和物理结构。 一、文件系统基础 1.文件的基本概念&#xff08;一切皆文件&#xff09; 文件&…

【漏洞复现】Netgear WN604 downloadFile.php 信息泄露漏洞(CVE-2024-6646)

0x01 产品简介 NETGEAR WN604是一款由NETGEAR&#xff08;网件&#xff09;公司生产的无线接入器&#xff08;或无线路由器&#xff09;提供Wi-Fi保护协议&#xff08;WPA2-PSK, WPA-PSK&#xff09;&#xff0c;以及有线等效加密&#xff08;WEP&#xff09;64位、128位和152…

AVL树超详解上

前言 学习过了二叉树以及二叉搜索树后&#xff08;不了解二叉搜索树的朋友可以先看看这篇博客&#xff0c;二叉搜索树详解-CSDN博客&#xff09;&#xff0c;我们在一般情况下对于二叉搜索树的插入与查询时间复杂度都是O(lgN)&#xff0c;是十分快的&#xff0c;但是在一些特殊…

视频监控平台LntonCVS视频融合共享平台智慧安防视频监控汇聚应用方案

LntonCVS是一款功能强大且灵活部署的安防视频监控平台。它支持多种主流标准协议&#xff0c;包括GB28181、RTSP/Onvif、RTMP等&#xff0c;同时能够兼容海康Ehome、海大宇等厂家的私有协议和SDK接入。该平台不仅提供传统的安防监控功能&#xff0c;还支持接入AI智能分析&#x…