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

如何通过SWIG将NumPy ndarray转为Eigen::Vector3d并解决内存泄漏

解决SWIG封装Eigen类型函数的类型转换与内存泄漏问题

核心问题

  • 初始调用时NumPy数组无法匹配Eigen::Vector3d const &类型,触发类型错误
  • 添加输入typemap后,返回的Eigen::Matrix<double,3,4>因SWIG无法自动管理内存,出现泄漏提示

完整解决方案

需要同时处理输入参数的类型转换和返回值的内存管理与类型转换,以下是修正后的关键代码:

1. 修正后的kinematics.i

%module kinematics
%{
    #define SWIG_FILE_WITH_INIT
    #include "kinematicsExample.h"
    #include <eigen3/Eigen/Dense>
%}

// 初始化NumPy接口支持
%include <numpy.i>
%numpy_include
%init %{
    import_array();
%}

// 输入typemap:NumPy ndarray → Eigen::Vector3d const &
%typemap(in) Eigen::Vector3d const & (Eigen::Vector3d temp_vec) {
    if (!PyArray_Check($input)) {
        PyErr_SetString(PyExc_TypeError, "必须传入NumPy数组");
        return NULL;
    }
    PyArrayObject* arr = reinterpret_cast<PyArrayObject*>($input);
    // 检查数组维度、长度和类型
    if (PyArray_NDIM(arr) != 1 || PyArray_DIM(arr, 0) != 3) {
        PyErr_SetString(PyExc_ValueError, "必须是长度为3的一维NumPy数组");
        return NULL;
    }
    if (PyArray_TYPE(arr) != NPY_DOUBLE) {
        PyErr_SetString(PyExc_TypeError, "数组类型必须为float64");
        return NULL;
    }
    double* data = reinterpret_cast<double*>(PyArray_DATA(arr));
    temp_vec << data[0], data[1], data[2];
    $1 = &temp_vec;
}

// 返回值typemap:Eigen::Matrix<double,3,4> → NumPy ndarray
%typemap(out) Eigen::Matrix<double,3,4> {
    npy_intp dims[2] = {3, 4};
    PyObject* arr = PyArray_SimpleNew(2, dims, NPY_DOUBLE);
    double* out_data = reinterpret_cast<double*>(PyArray_DATA(reinterpret_cast<PyArrayObject*>(arr)));
    
    // 将Eigen矩阵数据复制到NumPy数组
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 4; ++j) {
            out_data[i * 4 + j] = $1(i, j);
        }
    }
    
    $result = arr;
}

// 声明封装的函数(修正原代码中缺少的闭合括号)
Eigen::Matrix<double, 3, 4> forward_kinematics(const Eigen::Vector3d& q);

2. 关键修改说明

  • 输入typemap增强:增加了数组维度、长度、类型的严格检查,避免非法输入;用Eigen原生语法赋值更规范
  • 返回值typemap:直接将Eigen矩阵数据复制到NumPy数组并返回,替代SWIG默认生成的指针对象,彻底解决内存泄漏
  • NumPy初始化:添加%init块调用import_array(),确保NumPy接口正常工作

3. 测试验证

运行原test.py,现在会直接返回NumPy数组,无类型错误和内存泄漏提示:

import kinematics
import numpy as np

q_input = np.array([30,45,60], dtype=np.float64)
q_input = np.radians(q_input)

print(type(q_input))
print(q_input)

pose_matrix = kinematics.forward_kinematics(q_input)

print("Pose Matrix:")
print(pose_matrix)
print(type(pose_matrix))  # 输出:<class 'numpy.ndarray'>

额外提示

编译时需确保链接Eigen库,例如使用g++编译时添加参数-I/usr/include/eigen3;若需封装更多Eigen类型,可直接使用成熟的SWIG-Eigen接口库减少重复开发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:54:56