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

如何用SWIG封装返回可变float数组的C函数为Lua表?

用SWIG封装动态长度float数组并返回为Lua表的实现方案

我之前已经成功搞定了固定长度float数组的SWIG封装,Lua里直接就能拿到对应的表,现在又遇到了动态长度数组的需求,折腾了一番后终于搞定了,分享下我的实现过程:

先回顾下固定长度的实现

之前的C函数是这样的:

static void getArray(int size, float values[4]) {
    for (int i=0; i<size; ++i)
        values[i] = (float)i;
}

对应的SWIG接口里用现成的类型映射就搞定了:

%include <typemaps.i>
%apply (float OUTPUT[ANY]) {(float values[4])};

Lua里调用arr = my.getArray(4)直接拿到{0,1,2,3},非常顺畅。

动态长度数组的挑战与解决

现在要封装的是返回可变长度数组的C函数,原型是:

static void getArray(int size, float **values) {
    // 要在这里创建动态数组,最终转成Lua表返回
}

结合我用到的t_word结构体(里面有w_float的float字段,而且这块内存不用手动释放),我写了对应的SWIG类型映射,完美实现了需求。

第一步:完善C函数的逻辑

先把动态创建数组的代码写好:

#include <stdlib.h>

// 我的场景里用到的t_word结构体,供参考
typedef struct {
    float w_float;
} t_word;

static void getArray(int size, float **values) {
    // 动态分配对应大小的float数组
    *values = (float*)malloc(size * sizeof(float));
    if (!*values) return; // 内存分配失败直接返回

    // 填充数组数据,这里用t_word的w_float字段做示例
    for (int i = 0; i < size; ++i) {
        t_word temp_word;
        temp_word.w_float = (float)i * 1.2f; // 随便填的示例数据
        (*values)[i] = temp_word.w_float;
    }
}

第二步:编写SWIG的自定义类型映射

在SWIG的.i文件里,需要自定义类型映射来处理float**这个输出参数,把它转成Lua表:

%module my

%{
#include "your_code.h" // 引入你的C函数和t_word的头文件
%}

// 自定义out类型映射,把float**转成Lua表
%typemap(out) float** {
    if ($1 && *$1) {
        // 创建一个新的Lua表
        lua_newtable(L);
        int arr_size = $input; // 这里取函数的第一个参数size,注意参数位置要对应
        for (int i = 0; i < arr_size; ++i) {
            lua_pushnumber(L, (*$1)[i]);
            lua_rawseti(L, -2, i+1); // Lua表的索引是从1开始的
        }
        // 因为我的场景里t_word相关内存不用手动释放,这里就不用free了
        $result = lua_gettop(L);
    } else {
        // 数组为空的话返回nil
        lua_pushnil(L);
        $result = lua_gettop(L);
    }
}

// 调整参数的argout映射,配合out映射完成处理
%typemap(argout) float** {
    // 这里可以根据需求补充额外逻辑,比如清理临时变量等
}

// 把C函数暴露给Lua
void getArray(int size, float **values);

第三步:Lua里的调用效果

现在在Lua里直接调用就可以拿到动态生成的表了:

local dynamic_arr = my.getArray(6)
-- 得到的表是{0.0, 1.2, 2.4, 3.6, 4.8, 6.0}

一些关键注意点

  • 类型映射里的$input是指函数的第一个参数,如果你size不是第一个参数,要调整成对应的$input1、$input2这种格式。
  • 如果你的场景里是普通malloc的数组,需要考虑内存回收,可以用SWIG的%newobject或者自定义Lua的清理函数来避免内存泄漏。
  • 我的场景里t_word的内存不需要手动释放,所以省了free的步骤,大家要根据自己的内存管理逻辑调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:35:11