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

如何通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 14:30:33