c++与python进行管道通信,内附详细代码

因项目需求,需要实现python与c++间的通信。由于代码都在本地,因此采用管道通信的方式。

文章目录

一、管道简介

二、struct模块相关内容

三、代码demo

一、管道简介

管道是用于连接读/写进程的共享文件,pipe文件,本质上是内存中固定大小的缓冲区。管道通信的特点如下:
1.以流的形式读写:未满不读,已满不写,未空不写,已空不读,读后删除
2.同一时段只能单向通信,属于半双工通信
3.以先进先出(FIFO)方式组织数据传输
4.通过系统调用read()/write()函数进行读写操作

二、struct模块相关内容

此模块用于解析从c++端获取的数据,以及打包从python端发送的数据。

c++与python进行管道通信,内附详细代码_第1张图片
对齐方式:
c++与python进行管道通信,内附详细代码_第2张图片
格式符:
c++与python进行管道通信,内附详细代码_第3张图片

三、代码demo

下面是代码demo:
1.python创建管道,c++先写再读,python先读再写
python端代码:

import torch
import win32file
import win32pipe
import struct
from alog import MyAdd


class Mypipe():
    def __init__(self):
        # 数据内容
        self.end_context = None
        # 初始化模型
        self.model = torch.jit.load("model.pt")

    def pipe_init(self):
        # 创建管道
        self.python_pipe = win32pipe.CreateNamedPipe(r"\\.\\Pipe\\JUECE1-1",
                                                     win32pipe.PIPE_ACCESS_DUPLEX,
                                                     win32pipe.PIPE_TYPE_MESSAGE|win32pipe.PIPE_WAIT|win32pipe.PIPE_READMODE_MESSAGE,
                                                     win32pipe.PIPE_UNLIMITED_INSTANCES,
                                                     65536,
                                                     65536,
                                                     500,
                                                     None)

    def pipe_connect(self):
        win32pipe.ConnectNamedPipe(self.python_pipe, None)
        print("python 管道链接成功!")

    def pipe_run(self):
        print("管道开始运行!")
        while(1):
            # 计算格式大小
            formats = "<" + 'f' + 'd' * 10 + 'i' + "I" + 'd' + 'f'*6
            size = struct.calcsize(formats)
            print(size)

            res = win32file.ReadFile(self.python_pipe, size, None)
            res = res[1]
            res = struct.unpack(formats, res)
            print("接收到的数据:")
            print(res[0], res[1], res[2], res[3], res[4],
                  res[5], res[6], res[7], res[8], res[9],
                  res[10], res[11],
                  res[12], res[13], res[14], res[15],
                  res[16], res[17], res[18], res[19], )

            # 算法一:调用pt模型
            res = res[:10]
            tensor_data = torch.tensor(res, dtype=torch.float32)
            res_algo_1 = self.model(tensor_data).detach().numpy()
            # 算法二:调用普通算法
            res_algo_2 = MyAdd(res[0], res[1])

            res_list = []
            for i in res_algo_1:
                res_list.append(i)
            res_list.append(res_algo_2)

            print("计算出的数据:")
            print(res_list[0], res_list[1],res_list[2],res_list[3],res_list[4],res_list[5])
            self.end_context = struct.pack("f"*6, *res_list)
            win32file.WriteFile(self.python_pipe, self.end_context)

    def pipe_close(self):
        print("python 管道关闭!")
        win32pipe.DisconnectNamedPipe(self.python_pipe)


if __name__ == "__main__":
    mypipe = Mypipe()
    mypipe.pipe_init()
    mypipe.pipe_connect()
    mypipe.pipe_run()
    mypipe.pipe_close()

c++端代码:

#include 
#include 
#include 
#include
//发送数据的字节数
#define BUF_SIZE 2
#define RUNTIME 10
#define NODENUM 3
//字节对齐
#pragma pack(1)
using namespace std;

struct MMF
{
	unsigned int num;
	double kkk;
	float mmf;
	float mmf1;
	float mmf2;
	float mmf3;
	float mmf4;
	float mmf5;
};

struct StructReq 
{	
	float params2;
	double params[10];
	int params3;
	MMF mmf;
};
struct StructRes
{
	float params[3];
	float result[3];
};

int main()
{
	DWORD rLen = 0;
	DWORD wLen = 0;
	HANDLE hPipe;
	string pName;
	LPCWSTR wpName;
	StructRes res;
	StructReq req;

	req.params2 = 1.2;
	req.params3 = 4;
	for (int j = 0;j < 10;j++) {
		req.params[j] = 1;
	}
	req.mmf.num = 400;
	req.mmf.kkk = 4;
	req.mmf.mmf = 4.5;
	req.mmf.mmf1 = 5.5;
	req.mmf.mmf2 = 5.6;
	req.mmf.mmf3 = 5.7;
	req.mmf.mmf4 = 5.8;
	req.mmf.mmf5 = 5.9;

	if (!WaitNamedPipe(TEXT("\\\\.\\Pipe\\JUECE1-1"), NMPWAIT_WAIT_FOREVER)) {
		cout << "Connect NP Failed!" << endl;
		return 1;
	}
	hPipe = CreateFile(
			    TEXT("\\\\.\\Pipe\\JUECE1-1"),
				GENERIC_READ | GENERIC_WRITE,
				0,
				NULL,
				OPEN_EXISTING,
				FILE_ATTRIBUTE_NORMAL,
				NULL
			);
	if (INVALID_HANDLE_VALUE == hPipe)
	{
		cout << "Open Pipe Failed!" << endl;
		return 2;
	}
	WriteFile(hPipe, (byte*)&req, sizeof(StructReq), &wLen, 0);
	ReadFile(hPipe, (byte*)&res, sizeof(StructRes), &rLen, NULL);

	cout << res.params[0] << "\t" << res.params[1] << "\t" << res.params[2] << "\t" << res.result[0] << "\t"
		<< res.result[1] << "\t" << res.result[2] << endl;
	system("pause");
	return 0;
}

2.c++创建管道,c++先写再读,python先读再写
python端代码:

import torch
import win32file
import win32pipe
import struct
from alog import MyAdd


class Mypipe():
    def __init__(self):
        # 数据内容
        self.end_context = None
        # 初始化模型
        self.model = torch.jit.load("model.pt")

    def pipe_init(self):
        # 创建管道文件
        PIPE_NAME = r"\\.\Pipe\mypipe"
        self.python_pipe = win32file.CreateFile(
                                  PIPE_NAME,
                                  win32file.GENERIC_READ | win32file.GENERIC_WRITE,
                                  win32file.FILE_SHARE_WRITE, None,
                                  win32file.OPEN_EXISTING, 0, None)

    def pipe_run(self):
        print("管道开始运行!")
        while(1):
            formats = "<" + 'f' + 'd' * 10 + 'i' + "I" + 'd' + 'f'*6
            # formats = "<" + 'f' + 's'*10 + 'i'
            size = struct.calcsize(formats)
            print(size)

            res = win32file.ReadFile(self.python_pipe, size, None)
            res = res[1]
            res = struct.unpack(formats, res)
            print("接收到的数据:")
            print(res[0], res[1], res[2], res[3], res[4],
                  res[5], res[6], res[7], res[8], res[9],
                  res[10], res[11],
                  res[12], res[13], res[14], res[15],
                  res[16], res[17], res[18], res[19], )

            # 算法一:调用pt模型
            res = res[:10]
            tensor_data = torch.tensor(res, dtype=torch.float32)
            res_algo_1 = self.model(tensor_data).detach().numpy()
            # 算法二:调用普通算法
            res_algo_2 = MyAdd(res[0], res[1])

            res_list = []
            for i in res_algo_1:
                res_list.append(i)
            res_list.append(res_algo_2)

            print("计算出的数据:")
            print(res_list[0], res_list[1],res_list[2],res_list[3],res_list[4],res_list[5])
            self.end_context = struct.pack("f"*6, *res_list)
            win32file.WriteFile(self.python_pipe, self.end_context)


if __name__ == "__main__":
    mypipe = Mypipe()
    mypipe.pipe_init()
    mypipe.pipe_run()

c++端代码:

int main()
{
	//cpp创建管道
	printf("创建命名管道并等待连接\n");

	char pipeName[] = "\\\\.\\Pipe\\mypipe";
	HANDLE hPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT
		, PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_WAIT_FOREVER, 0);

	StructRes res;
	StructReq req;
	DWORD rLen = 0;
	DWORD wLen = 0;

	cout << "Client Started!" << endl;

	//waiting to be connected
	if (ConnectNamedPipe(hPipe, NULL) != NULL)
	{
		printf("连接成功,开始发送数据\n");

		if (!WriteFile(hPipe, (byte*)&req, sizeof(StructReq), &wLen, 0))
					{
						cout << "Request Failed!" << endl;
					}
					else {
						if (!ReadFile(hPipe, (byte*)&res, sizeof(StructRes), &rLen, NULL))
						{
							cout << "Response Failede!" << endl;
						}
						else {
							cout << res.params[0] <<"\t"<< res.params[1] << "\t" << res.params[2] << "\t" << res.result[0] << "\t"
								<< res.result[1] << "\t" << res.result[2] << endl;
						}
					}
	}



	DisconnectNamedPipe(hPipe);
	CloseHandle(hPipe);//关闭管道
	printf("关闭管道\n");

	system("pause");
	return 0;
}

注意事项:
1.c++端要加pragma pack(1),按一字节对齐
2.python端采用小端对齐的方式获取字节数

你可能感兴趣的:(python,c++,开发语言)