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

如何用SWIG将C++的uint8_t数组转换为Python列表?

解决C++通过SWIG返回uint8_t数组到Python列表的问题

首先你的原始C++代码存在严重错误:函数array_return返回局部数组random_array,局部变量在函数执行结束后会被销毁,返回其地址(或被截断为uint8_t值)属于未定义行为,这是一切问题的根源。下面提供两种可行方案:

方案一:使用std::vector<uint8_t>(推荐,安全无内存泄漏)

1. 修改C++代码

#include <vector>
#include <cstdint>

class MyClass
{
public:
    std::vector<uint8_t> array_return() {
        std::vector<uint8_t> random_array(100);
        // 示例:给数组填充0-99的uint8_t值
        for (int i = 0; i < 100; ++i) {
            random_array[i] = static_cast<uint8_t>(i);
        }
        return random_array;
    }
};

将该代码保存为myclass.h。

2. 编写SWIG接口文件(mymodule.i)

%module mymodule

// 引入SWIG对std::vector的支持模板
%include <std_vector.i>
// 为std::vector<uint8_t>生成包装代码
%template(UInt8Vector) std::vector<uint8_t>;

%{
#include "myclass.h"
%}

// 导入C++类定义
%include "myclass.h"

3. 编译生成Python模块

执行以下命令(需替换Python头文件路径为你的实际路径):

# 生成SWIG包装代码
swig -python -c++ mymodule.i
# 编译C++源文件和包装代码
g++ -fPIC -c myclass.cpp mymodule_wrap.cxx -I/usr/include/python3.10
# 生成共享库
g++ -shared myclass.o mymodule_wrap.o -o _mymodule.so

4. Python调用

import mymodule

obj = mymodule.MyClass()
my_list = obj.array_return()
print(my_list)  # 输出包含100个uint8_t值的Python列表

你之前说std::vector方案无效,大概率是因为没正确引入std_vector.i或未声明%template,按上述步骤即可解决。

方案二:返回动态分配的uint8_t指针(需手动管理内存)

1. 修改C++代码

#include <cstdint>
#include <cstdlib>

class MyClass
{
public:
    uint8_t* array_return() {
        // 动态分配100个uint8_t的内存
        uint8_t* random_array = static_cast<uint8_t*>(malloc(100 * sizeof(uint8_t)));
        // 填充示例值
        for (int i = 0; i < 100; ++i) {
            random_array[i] = static_cast<uint8_t>(i);
        }
        return random_array;
    }

    // 提供内存释放方法,避免泄漏
    void free_array(uint8_t* arr) {
        free(arr);
    }
};

2. 编写SWIG接口文件(mymodule.i)

%module mymodule

// 对返回的uint8_t*类型进行输出映射,转换为Python列表
%typemap(out) uint8_t* array_return {
    $result = PyList_New(100);
    for (int i = 0; i < 100; ++i) {
        // uint8_t是无符号整数,用PyLong_FromLong转换更准确(不要用PyFloat)
        PyList_SetItem($result, i, PyLong_FromLong(static_cast<long>($1[i])));
    }
    // 可选:如果不需要保留C端内存,可在此直接free($1),否则需手动调用free_array
}

%{
#include "myclass.h"
%}

%include "myclass.h"

3. 编译与调用

编译步骤同方案一,Python调用时需注意内存管理:

import mymodule

obj = mymodule.MyClass()
my_list = obj.array_return()
print(my_list)
# 注意:typemap转换后C端的指针已与Python列表无关,若typemap中未自动free,会造成内存泄漏
# 因此更推荐方案一

为什么你之前的typemap无效?

  • 原始C++函数返回类型是uint8_t,但实际返回数组名(退化为指针)会被截断为单个uint8_t值,类型不匹配,导致SWIG无法应用你写的uint8_t *array_return typemap。
  • 你使用PyFloat_FromDouble转换uint8_t值,会把整数转为浮点数,不符合需求,应该用PyLong_FromLong。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 08:13:12