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

如何通过LuaJIT FFI获取C函数输出的char*缓冲区值?

LuaJIT FFI调用C函数获取char*缓冲区值的问题解决

问题背景

你有一个编译好的SO文件,其中get_value函数会向传入的char*缓冲区写入数据,现在需要通过LuaJIT FFI调用该函数并获取缓冲区中的字符串值。你的C代码如下:

typedef struct MyStruct_s {
    int a;
}MyStruct;
void *init(char* host, int timeout) 
{
    void *handle = (void*)malloc(sizeof(MyStruct));
    if(handle == NULL) {
        printf("create myStruct falied\n");
    }

    return handle;
}
int get_value(void *handle, char *buffer, int *len) // 我希望将buffer传入Lua
{
    MyStruct* my_handle = (MyStruct*)handle;
    // my_handle执行操作
    if(buffer == NULL) {
        printf("buffer is NULL\n");
        return -1;
    }
    char tmp[10] = "hi there";
    memcpy(buffer, tmp, strlen(tmp));
    *len = strlen(tmp);

    return 0;
}

你尝试的Lua代码存在几个问题,导致无法正常工作,下面是修正方案:

错误分析与修正步骤

  1. 修正init函数的FFI声明
    你的C代码中init函数需要host和timeout两个参数,但Lua的ffi.cdef里写成了无参版本,这会导致调用init时参数不匹配,返回的handle可能无效。需要同步声明参数:

    ffi.cdef [[
        void *init(char* host, int timeout);
        int get_value(void *zkhandle, char *buffer, int *len);
    ]]
    

    调用时也要传入对应参数,比如:

    local handle = zkclient.init("127.0.0.1", 3000)
    
  2. 正确创建长度指针
    你直接用ffi.cast("int *", len)把整数1024转换成指针,这是错误的——这里需要的是一个指向int变量的指针,而不是把数值当成地址。应该先创建一个int类型的变量,再取它的地址:

    local node_len = ffi.new("int[1]", 1024) -- 创建一个长度为1的int数组,初始值1024,数组名就是指针
    
  3. 将char数组转换为Lua字符串
    调用get_value后,node_value是FFI的char数组,需要用ffi.string把它转换成Lua原生字符串,注意要传入实际的长度(node_len[0]),避免读取到多余的空字符:

    local lua_str = ffi.string(node_value, node_len[0])
    

完整修正后的Lua代码

local ffi = require("ffi")
local zkclient = ffi.load("zkclient")   

ffi.cdef [[
    void *init(char* host, int timeout);
    int get_value(void *zkhandle, char *buffer, int *len);
]]

-- 注意传入init函数需要的host和timeout参数
local handle = zkclient.init("127.0.0.1", 3000)
if handle == nil then
    kong.log.info("handle is nil ")
    return nil
end

-- 初始化1024大小的char缓冲区
local node_value = ffi.new('char[1024]', {0})
-- 创建存储长度的int指针,初始值为缓冲区大小
local node_len = ffi.new("int[1]", 1024)

local result = zkclient.get_value(handle, node_value, node_len)
if result == 0 then
    -- 将FFI char数组转换为Lua字符串
    local lua_str = ffi.string(node_value, node_len[0])
    kong.log.info("获取到的值:", lua_str)
else
    kong.log.info("调用get_value失败")
end

额外说明

  • ffi.new('char[1024]', {0})的写法是正确的,它会初始化一个1024字节的char数组并将所有元素置0。
  • 确保SO文件的路径正确,ffi.load会在系统默认库路径查找,如果SO在自定义路径,需要用绝对路径或者设置环境变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 03:49:57