You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

ESP32中Lua-C-API调用Lua函数出现空值调用错误求助

解决ESP32 Lua-C API调用时的"attempt to call a null value"错误

嘿,我帮你揪出这个错误的根源啦!你碰到的Unprotected error in call to Lua API (attempt to call a null value),核心问题是你只加载了Lua脚本,但没执行它——add.lua里的add函数根本没被注册到Lua状态机的全局环境中,所以lua_getglobal(L, "add")拿到的是nil,调用空值肯定会报错。下面一步步给你修复:

1. 补上Lua脚本的执行步骤

你现在的代码只用了luaL_loadfile,这个函数只是把Lua文件编译成字节码压到栈上,并没有执行。必须调用lua_pcall来运行这段字节码,这样add函数才会变成全局变量。修改加载文件的代码:

/* load Lua file */
if (luaL_loadfile(L, "add.lua")){
    printf("Error loading file: %s", lua_tostring(L, -1));
    lua_close(L); // 出错别忘了清理Lua状态机
    return;
}
// 执行编译后的Lua脚本,注册add函数到全局环境
if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
    printf("Error executing file: %s", lua_tostring(L, -1));
    lua_close(L);
    return;
}

2. 删掉重复的库初始化代码

你已经调用了luaL_openlibs(L),这个函数会自动加载所有Lua标准库(base、table、io、string、math这些全包含了),后面重复写的luaopen_base(L)luaopen_table(L)完全多余,甚至可能引发冲突,直接删掉就行:

/* initialize Lua */
lua_State* L = luaL_newstate();
luaL_openlibs(L);
// 删掉下面这些重复的代码
// openlibs(L); // 如果这个不是你自定义的函数,也建议检查下用途
// luaopen_base(L); 
// luaopen_table(L); 
// luaopen_io(L); 
// luaopen_string(L); 
// luaopen_math(L); 

3. 确认Lua文件的路径和烧录情况

在ESP32上,你得确保add.lua已经正确烧录到设备的文件系统(比如SPIFFS或FATFS)里,而且路径和你代码里写的"add.lua"一致。如果文件放在子目录,路径要写完整(比如"/data/add.lua")。

可以加个小检查,确认文件存在:

#include <sys/stat.h>
struct stat st;
if (stat("add.lua", &st) != 0) {
    ESP_LOGE(TAG, "Oh no! add.lua file not found!");
}

4. 给lua_call加个安全检查

为了避免以后再踩类似的坑,建议在调用函数前先检查拿到的是不是函数类型:

int luaadd (lua_State* L, int x, int y ) {
    int sum;
    /* 获取全局函数add */
    lua_getglobal(L, "add");
    // 检查栈顶是不是函数
    if (!lua_isfunction(L, -1)) {
        printf("Error: 'add' is not a function or not defined!");
        lua_pop(L, 1); // 弹出栈上的nil,避免栈不平衡
        return -1; // 返回错误码提示调用方
    }
    /* 压入参数 */
    lua_pushnumber(L, x);
    lua_pushnumber(L, y);
    /* 调用函数:2个参数,1个返回值 */
    lua_call(L, 2, 1);
    /* 获取结果 */
    sum = (int)lua_tointeger(L, -1);
    lua_pop(L, 1);
    return sum;
}

修复后的app_main核心片段

void app_main() {
    initialize_nvs();
#if CONFIG_STORE_HISTORY
    initialize_filesystem();
#endif
    initialize_console();

    /* 初始化Lua状态机 */
    lua_State* L = luaL_newstate();
    luaL_openlibs(L);

    /* 加载并执行Lua脚本 */
    if (luaL_loadfile(L, "add.lua")){
        printf("Error loading file: %s", lua_tostring(L, -1));
        lua_close(L);
        return;
    }
    if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
        printf("Error executing file: %s", lua_tostring(L, -1));
        lua_close(L);
        return;
    }

    /* 调用add函数 */
    int sum = luaadd(L, 10, 15 );
    printf( "The sum is %d\n", sum );

    /* 清理资源 */
    lua_close(L);
    printf("Finished");
}

最后总结

这个问题本质就是加载了Lua脚本但没执行,导致全局函数没被注册。按上面的步骤改完,应该就能正常调用add函数了。另外一定要确认add.lua的路径和烧录情况,别因为文件找不到白忙活一场~

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

火山引擎 最新活动