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

SWIG类型映射配置异常:调用Point::myfunc未获预期修改后的列表

问题描述

现有C++类Point包含如下方法:

int Point::myfunc(int a, std::vector<float> *b) 
{
     for (short int i = 0; i <= 10; i = i + 1)
        b->push_back(static_cast<float>(a * i));
    return 0;
}

编写的SWIG接口文件如下:

%module Point
%{
#include "Point.h"
%}
%include <std_string.i>
// Define typemaps for std::vector<float>*
%typemap(in) std::vector<float>* (std::vector<float> tmp) {
  $1 = &tmp;
}
%typemap(argout) std::vector<float>* {
  // Nothing needed here; the vector is modified in-place.
}
%include "Point.h"

通过命令swig -c++ -python -Wall Point.i生成Python模块后,调用代码如下:

a_list= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b=A.myfunc(3,a_list)
print (b)

得到的返回值为0,而非预期的修改后的列表,请问哪里配置错误?


错误分析与修正

你的配置存在三个核心问题:

  • 临时变量生命周期失效:in typemap里的tmp是局部临时变量,函数调用结束后就会被销毁,修改的内容根本传不回Python,还存在内存访问风险。
  • 未处理Python列表到C++ vector的转换:直接传入Python列表,但SWIG默认不知道如何将其映射到std::vector<float>*,需要引入标准vector库处理类型转换。
  • argout typemap未实现返回逻辑:原函数返回int类型,你需要把修改后的vector转成Python列表并追加到返回结果中,而非空实现。

修正后的SWIG接口文件

%module Point
%{
#include "Point.h"
%}
// 引入SWIG标准vector库,实现Python列表与std::vector的双向转换
%include <std_vector.i>
%template(FloatVec) std::vector<float>;

// 重新定义in typemap:将Python列表转为std::vector<float>,让函数指针指向它
%typemap(in) std::vector<float>* (std::vector<float> vec) {
    if (!PyList_Check($input)) {
        PyErr_SetString(PyExc_TypeError, "参数必须是列表");
        return NULL;
    }
    // 先把Python列表的元素复制到临时vector
    vec.resize(PyList_Size($input));
    for (Py_ssize_t i = 0; i < PyList_Size($input); ++i) {
        PyObject* item = PyList_GetItem($input, i);
        if (!PyFloat_Check(item) && !PyLong_Check(item)) {
            PyErr_SetString(PyExc_TypeError, "列表元素必须是数字");
            return NULL;
        }
        vec[i] = static_cast<float>(PyFloat_AsDouble(item));
    }
    $1 = &vec;
}

// 在argout typemap里把修改后的vector转为Python列表,追加到返回值中
%typemap(argout) std::vector<float>* {
    PyObject* list = PyList_New($1->size());
    for (size_t i = 0; i < $1->size(); ++i) {
        PyList_SetItem(list, i, PyFloat_FromDouble((*$1)[i]));
    }
    // 将列表作为第二个返回值,原函数的int返回值为第一个
    $result = SWIG_Python_AppendOutput($result, list);
}

%include "Point.h"

修正后的调用方式

import Point
# 创建Point类实例
A = Point.Point()
a_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 现在会返回两个值:原函数的int返回值、修改后的列表
ret_val, modified_list = A.myfunc(3, a_list)
print(ret_val)  # 输出0
print(modified_list)  # 输出原列表追加[0.0, 3.0, 6.0, ..., 30.0]后的结果

可选:直接返回修改后的列表

如果想忽略原int返回值,直接返回修改后的列表,可调整argout typemap:

%typemap(argout) std::vector<float>* {
    PyObject* list = PyList_New($1->size());
    for (size_t i = 0; i < $1->size(); ++i) {
        PyList_SetItem(list, i, PyFloat_FromDouble((*$1)[i]));
    }
    // 直接替换返回值为修改后的列表
    Py_XDECREF($result);
    $result = list;
}

调用代码简化为:

modified_list = A.myfunc(3, a_list)
print(modified_list)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 14:03:12