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

如何实现Lua与C双向交互:调用Lua主函数及注册C函数

C与Lua交互实现方案

核心需求

  • 在C代码中调用Lua脚本内的main函数
  • 将C语言的LoadTBL函数注册到Lua环境,供Lua脚本调用

一、适配C函数为Lua可调用接口并注册

Lua仅支持调用符合lua_CFunction签名的函数,因此需要先将C语言的LoadTBL封装成Lua兼容的接口,再注册到Lua全局环境。

修改后的C代码

#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

// 原业务逻辑函数
int LoadTBL (int val1, int val2, int val3) {
    // 此处编写你的业务逻辑,示例返回0表示成功,非0表示失败
    return 0;
}

// 封装为Lua可调用的接口函数
static int lua_LoadTBL(lua_State *L) {
    // 从Lua栈读取传入的3个整数参数
    int val1 = luaL_checkinteger(L, 1);
    int val2 = luaL_checkinteger(L, 2);
    int val3 = luaL_checkinteger(L, 3);

    // 调用原C函数
    int ret = LoadTBL(val1, val2, val3);

    // 向Lua栈压入返回结果和消息
    if (ret == 0) {
        lua_pushboolean(L, 1); // 成功返回true
        lua_pushstring(L, "执行成功");
    } else {
        lua_pushboolean(L, 0); // 失败返回false
        lua_pushstring(L, "参数无效或执行出错");
    }
    // 返回值数量:2个(布尔结果+消息字符串)
    return 2;
}

void read_test(void) {
    lua_State *L;
    L = luaL_newstate();
    luaL_openlibs(L);

    // 将封装后的函数注册到Lua全局环境,Lua中可直接调用LoadTBL
    lua_register(L, "LoadTBL", lua_LoadTBL);

    // 加载并执行Lua脚本(此时脚本已能访问LoadTBL函数)
    if (luaL_loadfile(L, "test.lua") || lua_pcall(L, 0, 0, 0))
    {
        printf("处理test.lua出错:%s\n", lua_tostring(L, -1));
        lua_close(L);
        return;
    }

    // 调用Lua中的main函数
    lua_getglobal(L, "main"); // 将main函数压入Lua栈
    // 调用main函数:无传入参数,期望2个返回值,0表示无错误处理函数
    if (lua_pcall(L, 0, 2, 0)) {
        printf("调用main函数出错:%s\n", lua_tostring(L, -1));
        lua_close(L);
        return;
    }

    // 读取main函数的返回结果
    int result = lua_toboolean(L, -2); // 第一个返回值(栈索引-2)
    const char *msg = lua_tostring(L, -1); // 第二个返回值(栈索引-1)
    printf("main执行结果:%s,消息:%s\n", result ? "成功" : "失败", msg);

    lua_close(L);
    printf("交互完成.\n");
}

int main() {
    read_test();
    return 0;
}

二、调整Lua脚本适配交互逻辑

原Lua脚本中的Init/End未定义,需改为有效类型(如字符串或整数),同时修正参数索引(原代码中value[1]为非整数,不符合C函数参数要求):

修改后的Lua代码(test.lua)

-- 定义测试表格,将Init/End改为字符串常量,参数取value[2]-value[4]
TBL = 
{
    { "Init",     0, 15, 0 },
    { "End",      1, 16, 0 }
}

function main()
    for key, value in pairs(TBL) do
        -- 调用C注册的LoadTBL函数,传入后三个整数参数
        local result, msg = LoadTBL(value[2], value[3], value[4]);
        if not result then 
            return false, msg;
        end
    end
        
    return true, "success";
end

关键逻辑说明

  1. C函数注册:通过lua_register将封装后的lua_LoadTBL绑定到Lua全局变量LoadTBL,Lua脚本即可直接调用。
  2. Lua函数调用:C代码通过lua_getglobal获取Lua的main函数,再用lua_pcall执行,最后从Lua栈中读取返回值。
  3. 栈操作规则:Lua与C交互依赖栈传递参数和返回值,必须严格遵循栈的操作顺序(如参数入栈顺序、返回值出栈顺序)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 16:45:32