调用 Lua API 时出现不受保护的错误(尝试调用空值)
Posted
技术标签:
【中文标题】调用 Lua API 时出现不受保护的错误(尝试调用空值)【英文标题】:Unprotected error in call to Lua API (attempt to call a null value) 【发布时间】:2018-05-10 09:11:04 【问题描述】:我目前正在为我的 ESP32 开发一个需要使用 Lua-C-API 的应用程序。 我的目标是从 C 中调用一个名为“add”的 Lua 函数,并在 ESP32 上刷新程序。
所以,在 Lua 代码(“add.lua”)中,我定义了函数“add”:
-- add two numbers
function add ( x, y )
return x + y
end
我调用接口的C代码如下:
/* Function luaadd */
int luaadd (lua_State* L, int x, int y )
int sum;
/* the function name */
lua_getglobal(L, "add");
/* the first argument */
lua_pushnumber(L, x);
/* the second argument */
lua_pushnumber(L, y);
/* call the function with 2 arguments, return 1 result */
lua_call(L, 2, 1);
/* get the result */
sum = (int)lua_tointeger(L, -1);
lua_pop(L, 1);
return sum;
/* Main function */
void app_main()
initialize_nvs();
#if CONFIG_STORE_HISTORY
initialize_filesystem();
#endif
initialize_console();
/* initialize Lua */
lua_State* L = luaL_newstate();
luaL_openlibs(L);
openlibs(L);
luaopen_base(L); /* opens the basic library */
luaopen_table(L); /* opens the table library */
luaopen_io(L); /* opens the I/O library */
luaopen_string(L); /* opens the string lib. */
luaopen_math(L); /* opens the math lib. */
/* load Lua file */
if (luaL_loadfile(L, "add.lua"))
printf("Error loading file: %s", lua_tostring(L, -1));
/* call the add function */
int sum;
sum = luaadd(L, 10, 15 );
/* print the result */
printf( "The sum is %d\n", sum );
/* cleanup Lua */
lua_close(L);
/* print 'Finished' to console */
printf("Finished");
这是整个 C 文件:
#include <modules.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "esp_system.h"
#include "esp_log.h"
#include "esp_console.h"
#include "esp_vfs_dev.h"
#include "driver/uart.h"
#include "linenoise/linenoise.h"
#include "argtable3/argtable3.h"
#include "esp_vfs_fat.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "sb.h"
#include <unistd.h>
#include <errno.h>
#include <unistd.h>
static const char* TAG = "Console";
/* Console command history can be stored to and loaded from a file.
* The easiest way to do this is to use FATFS filesystem on top of
* wear_levelling library.
*/
#if CONFIG_STORE_HISTORY
#define MOUNT_PATH "/data"
#define HISTORY_PATH MOUNT_PATH "/history.txt"
static void initialize_filesystem()
static wl_handle_t wl_handle;
const esp_vfs_fat_mount_config_t mount_config =
.max_files = 4,
.format_if_mount_failed = true
;
esp_err_t err = esp_vfs_fat_spiflash_mount(MOUNT_PATH, "storage", &mount_config, &wl_handle);
if (err != ESP_OK)
ESP_LOGE(TAG, "Failed to mount FATFS (0x%x)", err);
return;
#endif // CONFIG_STORE_HISTORY
static void initialize_nvs()
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES)
ESP_ERROR_CHECK( nvs_flash_erase() );
err = nvs_flash_init();
ESP_ERROR_CHECK(err);
static void initialize_console()
/* Disable buffering on stdin and stdout */
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
/* Minicom, screen, idf_monitor send CR when ENTER key is pressed */
esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR);
/* Move the caret to the beginning of the next line on '\n' */
esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
/* Install UART driver for interrupt-driven reads and writes */
ESP_ERROR_CHECK( uart_driver_install(CONFIG_CONSOLE_UART_NUM,
256, 0, 0, NULL, 0) );
/* Tell VFS to use UART driver */
esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM);
/* Initialize the console */
esp_console_config_t console_config =
.max_cmdline_args = 8,
.max_cmdline_length = 256,
#if CONFIG_LOG_COLORS
.hint_color = atoi(LOG_COLOR_CYAN)
#endif
;
ESP_ERROR_CHECK( esp_console_init(&console_config) );
/* Configure linenoise line completion library */
/* Enable multiline editing. If not set, long commands will scroll within
* single line.
*/
linenoiseSetMultiLine(1);
/* Tell linenoise where to get command completions and hints */
linenoiseSetCompletionCallback(&esp_console_get_completion);
linenoiseSetHintsCallback((linenoiseHintsCallback*) &esp_console_get_hint);
/* Set command history size */
linenoiseHistorySetMaxLen(100);
#if CONFIG_STORE_HISTORY
/* Load command history from filesystem */
linenoiseHistoryLoad(HISTORY_PATH);
#endif
int luaadd (lua_State* L, int x, int y )
int sum;
/* the function name */
lua_getglobal(L, "add");
/* the first argument */
lua_pushnumber(L, x);
/* the second argument */
lua_pushnumber(L, y);
/* call the function with 2 arguments, return 1 result */
lua_call(L, 2, 1);
/* get the result */
sum = (int)lua_tointeger(L, -1);
lua_pop(L, 1);
return sum;
void app_main()
initialize_nvs();
#if CONFIG_STORE_HISTORY
initialize_filesystem();
#endif
initialize_console();
/* initialize Lua */
lua_State* L = luaL_newstate();
luaL_openlibs(L);
openlibs(L);
luaopen_base(L); /* opens the basic library */
luaopen_table(L); /* opens the table library */
luaopen_io(L); /* opens the I/O library */
luaopen_string(L); /* opens the string lib. */
luaopen_math(L); /* opens the math lib. */
/* load Lua file */
if (luaL_loadfile(L, "add.lua"))
printf("Error loading file: %s", lua_tostring(L, -1));
/* call the add function */
int sum;
sum = luaadd(L, 10, 15 );
/* print the result */
printf( "The sum is %d\n", sum );
/* cleanup Lua */
lua_close(L);
/* print 'Finished' to console */
printf("Finished");
当我现在将它刷到我的 ESP32 上时,我收到以下消息:
错误加载文件:无法打开 add.lua:没有这样的文件或 directoryPANIC:调用 Lua API 时出现不受保护的错误(尝试调用 一个 nil 值)abort() 在核心 0 上的 PC 0x4016b808 处被调用
你知道如何解决这个问题吗?我的“add.lua”文件与 C 文件在同一目录中。
【问题讨论】:
尝试将 lua 文件格式更改为没有 BOM 的 UTF-8 吗? 【参考方案1】:正如post 中所述,您需要./add.lua
从当前目录加载文件。您也可以尝试使用绝对路径。
【讨论】:
非常感谢您的帮助!但是,在我的情况下,使用绝对路径以及“./add.lua”并没有帮助。 你已经看过askubuntu.com/questions/133389/…了吗?也许它可以帮助?【参考方案2】:luaL_loadfile
仅加载文件但不执行其内容。函数add
仅在文件执行时定义。使用luaL_dofile
加载并执行文件。
【讨论】:
谢谢。我试过luaL_dofile。但是,这不起作用,因为根本找不到文件“add.lua”(尽管如此执行)。以上是关于调用 Lua API 时出现不受保护的错误(尝试调用空值)的主要内容,如果未能解决你的问题,请参考以下文章
尝试使用多个值插入 SQL Server 时出现不正确的语法错误
Laravel,尝试通过 AJAX 向控制器传递数据时出现不匹配的令牌错误