如何通过PyRun_String获取Python返回的MAVLink姿态PyObject并转为C对象?
C/C++对接pymavlink消息对象的解决方案
核心思路:直接提取Python对象属性
MAVLink_attitude_message是pymavlink封装的Python类实例,所有消息字段都是公开属性,没必要强行转换成C结构体,用Python C API直接读取每个字段即可。
示例代码:
#include <Python.h> // 假设你已经通过PyRun_String拿到了attitude_msg这个PyObject指针 PyObject* attitude_msg = ...; // 你的获取逻辑 // 逐个读取消息字段对应的属性 PyObject* roll_obj = PyObject_GetAttrString(attitude_msg, "roll"); PyObject* pitch_obj = PyObject_GetAttrString(attitude_msg, "pitch"); PyObject* yaw_obj = PyObject_GetAttrString(attitude_msg, "yaw"); PyObject* rollspeed_obj = PyObject_GetAttrString(attitude_msg, "rollspeed"); PyObject* pitchspeed_obj = PyObject_GetAttrString(attitude_msg, "pitchspeed"); PyObject* yawspeed_obj = PyObject_GetAttrString(attitude_msg, "yawspeed"); // 把Python对象转成C语言可用的数值类型 double roll = PyFloat_AsDouble(roll_obj); double pitch = PyFloat_AsDouble(pitch_obj); double yaw = PyFloat_AsDouble(yaw_obj); double rollspeed = PyFloat_AsDouble(rollspeed_obj); double pitchspeed = PyFloat_AsDouble(pitchspeed_obj); double yawspeed = PyFloat_AsDouble(yawspeed_obj); // 记得释放Python对象的引用,避免内存泄漏 Py_DECREF(roll_obj); Py_DECREF(pitch_obj); Py_DECREF(yaw_obj); Py_DECREF(rollspeed_obj); Py_DECREF(pitchspeed_obj); Py_DECREF(yawspeed_obj);
解决return语句无效的问题
如果是写Python扩展模块
要确保函数返回类型是PyObject*,并且返回的对象引用计数正确:
- 不要提前释放要返回的对象
- 如果获取到的
attitude_msg是合法对象,直接返回它即可,Python会自动处理引用计数
示例扩展函数:
static PyObject* get_attitude(PyObject* self, PyObject* args) { // 执行你的Python脚本逻辑,获取姿态消息对象 PyObject* attitude_msg = PyRun_String("your_python_code_here", Py_file_input, globals, locals); if (attitude_msg == NULL) { return NULL; // 自动抛出Python异常 } // 直接返回对象,不要在这里调用Py_DECREF return attitude_msg; }
如果是嵌入式Python环境调用
要正确接收PyRun_String的返回值,使用完后再释放:
PyObject* result = PyRun_String("get_attitude_message()", Py_eval_input, globals, locals); if (result != NULL) { // 在这里处理result中的属性 // ... // 处理完释放引用 Py_DECREF(result); } else { PyErr_Print(); // 打印错误信息排查问题 }
编译与环境注意事项
树莓派环境下编译C代码时,要指定Python3.9的头文件和链接库,编译命令示例:
gcc -shared -fPIC -I/usr/include/python3.9 -lpython3.9 your_code.c -o your_module.so
另外,每次调用PyObject_GetAttrString后要检查返回值是否为NULL,如果是NULL说明属性不存在,调用PyErr_Print()能打印具体错误原因。
如果需要频繁处理这类消息,可以定义一个C结构体来存储提取后的字段,方便后续使用:
typedef struct { double roll; double pitch; double yaw; double rollspeed; double pitchspeed; double yawspeed; } MAVAttitude; MAVAttitude convert_to_c_attitude(PyObject* py_attitude) { MAVAttitude att = {0}; PyObject* roll_obj = PyObject_GetAttrString(py_attitude, "roll"); att.roll = PyFloat_AsDouble(roll_obj); Py_DECREF(roll_obj); // 其他字段同理复制逻辑 return att; }
内容的提问来源于stack exchange,提问作者MaryG
相关产品推荐
相关产品推荐

