调用 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 时出现不受保护的错误(尝试调用空值)的主要内容,如果未能解决你的问题,请参考以下文章

发布到 Web API 时出现不支持的媒体类型错误

尝试子查询时出现不明确的列名错误

尝试使用多个值插入 SQL Server 时出现不正确的语法错误

Laravel,尝试通过 AJAX 向控制器传递数据时出现不匹配的令牌错误

调用 GMAIL API 时出现间歇性错误 - “调用者没有权限”

当我尝试对文件IO使用nextint()时出现不匹配异常错误