c - 调用 Lua API 时出现不 protected 错误(尝试调用空值)

标签 c api lua esp32

我目前正在为 ESP32 开发一个应用程序,需要使用 Lua-C-API。 我的目标是从 C 调用名为“add”的 Lua 函数,并将程序烧写到 ESP32 上。

所以,在Lua代码(“add.lua”)中我定义了函数“add”:

    -- add two numbers
    function add ( x, y )
    return x + y
    end    

我调用接口(interface)的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 上时,我收到以下消息:

Error loading file: cannot open add.lua: No such file or directoryPANIC: unprotected error in call to Lua API (attempt to call a nil value) abort() was called at PC 0x4016b808 on core 0

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

最佳答案

如本 post 中所述,您需要 ./add.lua 从当前目录加载文件。您也可以尝试使用绝对路径。

关于c - 调用 Lua API 时出现不 protected 错误(尝试调用空值),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50269340/

相关文章:

lua - 如何在 Linux 系统上安装多个版本的 Lua(并让它们与 Luarocks 配合使用)?

c - 为什么内存会损坏?

c - 编写我自己的 shell - 无法正确处理 ctrl+c (SIGINT)

python - 使用 Python 的请求对表单数据进行 POST 请求

Azure数据工厂管道: conditional checking on variable activity

eclipse - LuaEclipse 插件中 Lua 的语法高亮显示

parsing - 从文本文件lua中解析科学数字

c - 使用字符数组作为长整型数组

c - 常用的libc头文件有哪些及其功能

api - REST API - 在单个请求中批量创建或更新