最近写项目用到了C++与Python,两个之间需要通信,所以就记录一下自己的学习过程防止自己忘记,代码主要参考这篇博主的博客,上链接:
参考博客
我主要需要的是C++发送,Python来接收,稍微改了一下,代码如下:
C++发送:
#include <Windows.h>
#include <iostream>
//发送数据的字节数
#define BUF_SIZE 2
using namespace std;
int main()
{
HANDLE h_pipe;
char buf_msg[] = "1";//主要发送的数据
DWORD num_rcv;//实际收到的字节数
cout << "Try to connect named pipe..." << endl;
//连接命名管道
if (WaitNamedPipe("\\\\.\\pipe\\test_pipe", NMPWAIT_WAIT_FOREVER))
{
//打开指定的命名管道
h_pipe = CreateFile("\\\\.\\pipe\\test_pipe", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (h_pipe == INVALID_HANDLE_VALUE)
{
cerr << "Failed to open the appointed named pipe!Error code:" << GetLastError() << endl;
system("pause");
return 1;
}
else
{
if (WriteFile(h_pipe, buf_msg, BUF_SIZE, &num_rcv, nullptr))
{
cout << "Message sent successfully..." << endl;
}
else
{
cerr << "Failed to send message!Error code:" << GetLastError() << endl;
CloseHandle(h_pipe);
system("pause");
return 1;
}
}
CloseHandle(h_pipe);
}
system("pause");
return 0;
}
Python接收:
import win32file
import win32pipe
import struct
import threading
def recv_pipe(PIPE_NAME, PIPE_BUFFER_SIZE):
while True:
named_pipe = win32pipe.CreateNamedPipe(PIPE_NAME,
win32pipe.PIPE_ACCESS_DUPLEX,
win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_WAIT | win32pipe.PIPE_READMODE_MESSAGE,
win32pipe.PIPE_UNLIMITED_INSTANCES,
PIPE_BUFFER_SIZE,
PIPE_BUFFER_SIZE, 500, None)
try:
while True:
try:
win32pipe.ConnectNamedPipe(named_pipe, None)
data = win32file.ReadFile(named_pipe, PIPE_BUFFER_SIZE, None)
if data is None:
continue
# print("Received msg:", data)
recv_msg = struct.unpack('<2s', data[1])
recv_msg = recv_msg[0].decode("utf-8")
print("Parsed message:", recv_msg)
except BaseException as e:
print("Exception1:", e)
break
finally:
try:
win32pipe.DisconnectNamedPipe(named_pipe)
except BaseException as e:
print("Exception2:", e)
break
if __name__ == "__main__":
pipe_name = r"\\.\pipe\test_pipe"
pipe_buffer_size = 65535
receive_thread = threading.Thread(target=recv_pipe, args=(pipe_name, pipe_buffer_size))
receive_thread.start()
说明:
C++程序
- C++程序中的宏定义
BUF_SIZE
可以当作你要写入数据的字节数。定义的DWORD类型的num_rcv
是实际收到的字节数,这个好像没什么影响不需要管。BUF_SIZE
的话根据你要传的数据来定吧,我这里只是传一个信号,所以没设太大,就设成了2。参考博客中说python收到数据后面还有一堆乱码可能是BUF_SIZE
设得比较大(1024),而传输的数据本身只有几个字节,我本人试过那样确实后面会有一堆别的东西,当我设成和数据大小一样时就没有了,所以我猜测可能是BUF_SIZE
设得比较大。 - 然后就是代码中连接命名管道那句如图:
图中框出的两个地方要一致,不一致就发不出去。
WaitNamedPipe主要来等待命名管道的出现,这里我命名的是test_pipe,如果等到管道即WaitNamedPipe返回true,下来就打开指定的命名管道即下面这句:
//打开指定的命名管道
h_pipe = CreateFile("\\\\.\\pipe\\test_pipe", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
Python程序
- Python的接收程序我是用线程来接收,方便多线程运行。
- 收到数据后,用struct库对数据进行解析,data是一个元组,第一个元素是0(我也不知道为什么是0),第二个元素就是我发送的数据,所以取得data[1],这样得到的recv_msg是一个二进制字符串,print的话前面带有b,强迫症的我为了看起来和普通字符串一样,就对字符串以utf-8做了解码
运行结果:
先启动python准备接收,然后启动C++程序发送
发送完成:
接收结果:
接收到发送的数据1,通信没问题,下面的异常应该是程序发送完成后关闭线程句柄导致的,不过影响不大。