首页 > 解决方案 > 调用 Lua API 时出现不受保护的错误(尝试调用空值)

问题描述

我目前正在为我的 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:没有这样的文件或目录PANIC:调用 Lua API 时出现不受保护的错误(尝试调用 nil 值)在核心 0 上的 PC 0x4016b808 上调用了 abort()

你知道如何解决问题吗?我的“add.lua”文件与 C 文件位于同一目录中。

标签: capiluaesp32

解决方案


luaL_loadfile仅加载文件但不执行其内容。该函数add仅在文件执行时定义。用于luaL_dofile加载和执行文件。


推荐阅读