如何使用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。
修正步骤
- 获取Serial类对象:导入serial模块后,通过
PyObject_GetAttrString提取模块内的Serial类。 - 正确调用构造函数:无参实例用
PyObject_CallNoArgs创建;需传参时可使用PyObject_CallFunction或PyObject_Call。 - 维护引用计数:严格遵循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
相关产品推荐
相关产品推荐

