QT(6.5) cmake构建C++编程,c++与python进行通信(命名管道)

QT(6.5) cmake构建C++编程,c++与python进行通信(命名管道)

  1. 首先,c++端编写命名管导通信代码
#include <QDebug>
#include <windows.h>

bool fifp_cpp(){
    // 创建命名管道(用于读写)
    HANDLE hPipe;
    hPipe = CreateNamedPipeW(
        L"\\\\.\\pipe\\pretectPipe",   // 管道名称,L不可少,其中pretectPipe为自定义名称
        PIPE_ACCESS_DUPLEX,         // 读写模式
        PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
        1,                         // 最大实例数
        0,                         // 输出缓冲区大小(在此处,我们将依赖系统的默认大小)
        0,                         // 输入缓冲区大小(在此处,我们将依赖系统的默认大小)
        0,                         // 默认超时时间
        NULL);                     // 安全描述符,默认为空

    if (hPipe == INVALID_HANDLE_VALUE) {
        qDebug() << "CreateNamedPipe failed with error(INVALID_HANDLE_VALUE): " << GetLastError() << "\n";
        return false;
    }
    // 此时C++进程已经准备好了命名管道
    qDebug() << "管道创建成功" << "\n";

    // 等待客户端连接
    if (ConnectNamedPipe(hPipe, NULL) == FALSE) {  //没有客户端连接(连接超时)
        if (GetLastError() != ERROR_PIPE_CONNECTED) {  //不是已有客户端连接导致连接超时
            qDebug() << "ConnectNamedPipe failed with error(超时): " << GetLastError() << "\n";
            CloseHandle(hPipe);
            return false;
        }
    }
    qDebug() << "管道已被连接" << "\n";
    // C++写入数据
    std::string message_from_cpp = "1";  
    //假如约定c++发送"1"为全部数据,python发送"2"为全部数据,"0"为结束标记,皆以\0为结束标记
    //注C++字符串结尾会自动包含\0,字符串的length不包含\0的长度,所以下面写入管道时将长度+1
    DWORD bytesWritten;
    WriteFile(hPipe, message_from_cpp.c_str(), static_cast<DWORD>(message_from_cpp.length() + 1), &bytesWritten, NULL); // 包含结束符'\0'
    qDebug() << "发送开始信号" << "\n";  //约定c++发送1
    // C++读取数据(假定Python会在后续阶段写入数据)
    char buffer[1024];
    DWORD bytesRead;
    bool pipeStop = false;
    int read_total = 0;
    do {
        if (PeekNamedPipe(hPipe, NULL, 0, NULL, &bytesRead, NULL)) {
            if (bytesRead > 0) {
                ReadFile(hPipe, buffer + read_total, sizeof(buffer) - read_total, &bytesRead, NULL);
                read_total += bytesRead;
                //qDebug() << "Received from Python: " << buffer << "\n";
                if(buffer[read_total - 1] == '\0'){
                    if(buffer[0] == '2'){
                    //因为约定只发1个字符,所以buffer[0]是确定的,实践中根据实际情况读取你的数据
                        qDebug() << "收到python数据" << "\n";
                        WriteFile(hPipe, message_from_cpp.c_str(), static_cast<DWORD>(message_from_cpp.length() + 1), &bytesWritten, NULL); // 继续发送,包含结束符'\0'
                        }
                    else if(buffer[0] == '0'){
                        qDebug() << "python给出关闭信号" << "\n";
                        pipeStop = true;
                        }
                    read_total = 0; //计数归零,下一轮循环
                }
            }
        } else {
            Sleep(25); // 短暂休眠,以免过度消耗CPU
            //qDebug() << "等待信号" << "\n";
        }
    } while (!pipeStop);
    CloseHandle(hPipe);
    qDebug() << "fifp通信结束" << "\n";
    return true;
}
  1. 其次python编写命名管道通信代码
import win32file
import win32pipe
import time

def fifp_python():
    hPipe = None
    # 确保C++进程已创建管道并准备好接收数据
    # Python进程尝试连接命名管道
    pipStop = false
    while not hPipe:
        try:
            # 尝试连接命名管道,如果管道还未创建,则会失败,此时等待一段时间后重试
            hPipe = win32file.CreateFile(
                "\\\\.\\pipe\\pretectPipe", # 与c++端保持一致
                win32file.GENERIC_READ | win32file.GENERIC_WRITE,  # 读写模式
                0,  # 不共享此管道
                None,  # 默认安全性
                win32file.OPEN_EXISTING,  # 打开已存在的管道
                0,  # 标准文件属性
                None)  # 无模板文件句柄
        except OSError as ex:
            if ex.winerror != 2:  # 如果错误号不是2(文件未找到),则抛出异常
                print("命名管道连接错误")
                return False
            time.sleep(0.025)  # 管道未准备好,等待1秒后重试
    while not pipStop:
        # 检查管道中是否有数据
        read_bytes, bytes_avail, _ = win32pipe.PeekNamedPipe(hPipe, 0)
        buffer = b''
        if bytes_avail > 0:
            # 读取管道中的数据
            data = win32file.ReadFile(hPipe, bytes_avail, None)[1]
            buffer += data
            #  print(buffer[0])
            # 检查是否接收到特定数据
            if buffer == b'1\0':
                print("Python接收C++数据成功")
                # 发送响应数据
                win32file.WriteFile(hPipe, b'2\0', None)
            elif buffer == b'0\0':
                print("Python接收到关闭信号")
                win32file.WriteFile(hPipe, b'0\0', None)
                win32file.CloseHandle(hPipe)
                pipStop = True
        else:
            # 管道中无数据,短暂休眠以避免过度CPU使用
            time.sleep(0.025)
    return True
  1. 最后,在需要使用时在c++端先调用函数,再调用python端的函数,便可通过命名管道进行不同语言、进程间的通信进行数据交换

相关推荐

  1. QT(6.5) cmake构建C++编程,多线程

    2024-03-31 07:18:04       15 阅读
  2. c/c++ | 使用cmake 对项目进行构造

    2024-03-31 07:18:04       41 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-31 07:18:04       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-31 07:18:04       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-31 07:18:04       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-31 07:18:04       18 阅读

热门阅读

  1. CSS3 简介

    2024-03-31 07:18:04       15 阅读
  2. @RequestParam、@PathVariable、@RequestBody

    2024-03-31 07:18:04       13 阅读
  3. CSS3新增的语法(一)

    2024-03-31 07:18:04       18 阅读
  4. 【WPF应用23】wpf 基本控件-RichTextBox详解与示例

    2024-03-31 07:18:04       18 阅读
  5. 安全算法 - 摘要算法

    2024-03-31 07:18:04       18 阅读
  6. 手搓 Docker Image Creator(DIC)工具(01):前言

    2024-03-31 07:18:04       20 阅读
  7. 达梦DCA 培训及考试总结

    2024-03-31 07:18:04       21 阅读
  8. zookeeper常见命令详解2

    2024-03-31 07:18:04       17 阅读