能否将Python pyserial的Serial对象转为句柄传递给C子进程?
关于串口句柄/文件描述符传递给C子进程的解答
咱们先逐个拆解你的问题,结合不同操作系统的情况来聊:
1. 能否将Serial对象转换为文件描述符传递给C程序?
这个得分平台来看:
- Unix-like系统(Linux、macOS等):完全可以。pyserial的
Serial对象自带fileno()方法,调用它就能拿到对应串口的文件描述符(整数类型)。你可以把这个描述符通过命令行参数传给C程序,或者直接作为subprocess.Popen的stdin/stdout参数传递,C程序里直接用这个fd做read()/write()操作,或者用fdopen()转成FILE*来用。 - Windows系统:不行。Windows的“文件句柄”和Unix的“文件描述符”是两套不同的机制,pyserial在Windows下的
Serial对象也没有fileno()方法。不过咱们有其他办法解决第二个问题。
2. Python打开串口后,传递句柄给用CreateFile的C子进程?
可以实现,但需要适配Windows的句柄机制,步骤如下:
第一步:Python端获取串口句柄并传递
pyserial在Windows下的Serial对象有个handle属性,能直接拿到Win32 API的串口句柄(整数类型)。你需要先以非独占模式打开串口(避免子进程无法访问),然后把这个句柄值作为命令行参数传给C子进程:
import serial import subprocess # 打开串口时设置exclusive=False,允许共享访问 ser = serial.Serial('COM3', 9600, exclusive=False) # 获取Win32句柄 serial_handle = ser.handle # 把句柄作为命令行参数传给C程序 subprocess.Popen(['./your_c_program.exe', str(serial_handle)])
第二步:C程序端接收并使用句柄
C程序拿到句柄值后,不能直接用,最好通过DuplicateHandle()复制一个属于子进程的句柄(避免权限或生命周期问题),之后就可以用这个复制后的句柄做ReadFile()/WriteFile()操作了:
#include <windows.h> #include <stdio.h> int main(int argc, char* argv[]) { if (argc < 2) { printf("Usage: %s <serial_handle>\n", argv[0]); return 1; } // 把命令行参数转成HANDLE HANDLE parent_serial_handle = (HANDLE)atoi(argv[1]); HANDLE child_serial_handle; // 复制句柄到当前进程 if (!DuplicateHandle( GetCurrentProcess(), // 源进程(父进程) parent_serial_handle, // 源句柄 GetCurrentProcess(), // 目标进程(当前子进程) &child_serial_handle, // 输出复制后的句柄 0, // 不需要额外权限 FALSE, // 不继承给子进程的子进程 DUPLICATE_SAME_ACCESS // 复制和源句柄相同的权限 )) { printf("DuplicateHandle failed, error code: %d\n", GetLastError()); return 1; } // 示例:读取串口数据 char buffer[1024]; DWORD bytes_read; if (ReadFile(child_serial_handle, buffer, sizeof(buffer)-1, &bytes_read, NULL)) { buffer[bytes_read] = '\0'; printf("Received from serial: %s\n", buffer); } else { printf("ReadFile failed, error code: %d\n", GetLastError()); } // 记得关闭句柄 CloseHandle(child_serial_handle); return 0; }
关键注意点
- Windows下必须打开串口时设置
exclusive=False,否则子进程无法访问该句柄; - 一定要用
DuplicateHandle()复制句柄,直接使用父进程的句柄可能会因为权限或进程退出导致异常; - Unix系统下的方案更简单,直接用
fileno()拿到fd传递即可,C程序无需额外处理,直接用fd操作就行。
内容的提问来源于stack exchange,提问作者MichaelW
相关产品推荐
相关产品推荐

