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

如何使用Python C API创建PySerial的Serial类实例?

在Python C API中创建PySerial Serial实例的正确方法

目标是通过Python C API创建PySerial的Serial类实例,对应Python代码如下:

import serial
test = serial.Serial()

现有C代码尝试导入serial模块并创建实例,但存在错误,无法正确生成Serial对象。

核心错误分析

当前代码的问题点:

  • PyImport_ImportModule("serial")导入的是serial模块对象,而非模块内的Serial类,直接用Py_TYPE(PySerialObject)获取的是模块的类型(module),不是Serial类本身。
  • PyObject_CallOneArg的参数构造错误,Py_BuildValue("serial.Serial()")不是合法的参数格式,且无参构造应该使用PyObject_CallNoArgs。

修正步骤

  1. 获取Serial类对象:导入serial模块后,通过PyObject_GetAttrString提取模块内的Serial类。
  2. 正确调用构造函数:无参实例用PyObject_CallNoArgs创建;需传参时可使用PyObject_CallFunction或PyObject_Call。
  3. 维护引用计数:严格遵循Python C API规则管理对象引用,避免内存泄漏。

修正后的代码片段

模块初始化函数

#include <Python.h>

// 全局变量存储Serial类对象(需管理引用计数)
static PyObject *PySerialClass = NULL;

PyMODINIT_FUNC PyInit_Module(void)
{
    PyObject *m;
    PyObject *serial_module;

    // 初始化自定义类型
    if (PyType_Ready(&SubClassType) < 0) return NULL;

    // 创建模块
    m = PyModule_Create(&Module_module);
    if (m == NULL) return NULL;

    // 将自定义类添加到模块
    Py_INCREF(&SubClassType);
    if (PyModule_AddObject(m, "SubClass", (PyObject *)&SubClassType) < 0) {
        Py_DECREF(&SubClassType);
        Py_DECREF(m);
        return NULL;
    }

    // 导入serial模块
    serial_module = PyImport_ImportModule("serial");
    if (serial_module == NULL) {
        Py_DECREF(&SubClassType);
        Py_DECREF(m);
        return NULL;
    }

    // 获取模块内的Serial类对象
    PySerialClass = PyObject_GetAttrString(serial_module, "Serial");
    Py_DECREF(serial_module); // 模块对象不再使用,释放引用
    if (PySerialClass == NULL) {
        Py_DECREF(&SubClassType);
        Py_DECREF(m);
        return NULL;
    }

    return m;
}

SubClass_new函数

static PyObject *SubClass_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    SubClassObject *self;
    self = (SubClassObject *)type->tp_alloc(type, 0);
    if (self == NULL) return NULL;

    self->serial = NULL;

    // 创建无参Serial实例
    self->serial = PyObject_CallNoArgs(PySerialClass);
    if (self->serial == NULL) {
        Py_DECREF(self); // 创建失败,释放self
        return NULL;
    }

    return (PyObject *)self;
}

额外注意事项

  • 引用计数清理:PySerialClass作为全局变量,需在模块退出时释放引用(可在模块的清理函数中调用Py_XDECREF(PySerialClass))。
  • 带参构造示例:如果需要传入端口、波特率等参数,可使用PyObject_CallFunction:
    // 创建Serial("COM1", 9600)实例
    self->serial = PyObject_CallFunction(PySerialClass, "si", "COM1", 9600);
    
  • 依赖声明:确保pyproject.toml中添加pyserial依赖:
    [project.dependencies]
    pyserial = ">=3.0"
    

内容的提问来源于stack exchange,提问作者Cutyno

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 01:20:56