You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:34:30