恐慌:调用 Lua API 时发生未受保护的错误(未定义符号:lua_gettop)

PANIC: unprotected error in call to Lua API (undefined symbol: lua_gettop)

我的环境是Lua-5.4.2 Luasocket-3.0-rc1。 当我直接 运行 lua 脚本时,它工作成功。 当我运行它通过c语言,它告诉我错误。

错误消息是: 恐慌:调用 Lua API 时发生未受保护的错误(错误 运行ning 脚本:从文件 '/usr/local/lib/lua/5.4/[=27= 加载模块 'socket.core' 时出错.so':未定义的符号:lua_gettop) 中止(核心转储)

有人知道为什么吗?

lua脚本代码为:(test.lua)

#!/usr/local/bin/lua
local socket = require("socket")
print(socket._VERSION)

c代码为:(main.c)

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
int main(void)
{
    lua_State *L;
    L = luaL_newstate();
    luaopen_base(L);
    luaL_openlibs(L);
        
    printf("lua enter\n");
    if (luaL_dofile(L, "test.lua"))
    {
        luaL_error(L, "error running script: %s", lua_tostring(L, -1));
    }
    printf("lua exit\n");
     
    while(1) pause();
    lua_close(L);
    return 0;
}

tl;dr:将 -Wl,-E 传递给 GCC。

我能够使用此 Docker 文件重现您的问题:

FROM gcc:11.1.0
RUN wget https://www.lua.org/ftp/lua-5.4.2.tar.gz \
 && git clone https://github.com/diegonehab/luasocket.git
RUN tar zxf lua-5.4.2.tar.gz \
 && cd lua-5.4.2 \
 && make linux \
 && make install \
 && cd ../luasocket \
 && git checkout 5b18e475f38fcf28429b1cc4b17baee3b9793a62 \
 && make linux LUAV=5.4 \
 && make install LUAV=5.4
COPY test.lua main.c ./

当我在生成的 Docker 容器中 运行 lua test.lua 时,它工作正常。当我 运行 gcc -o test main.c /usr/local/lib/liblua.a -ldl -lm -Wl,-rpath='/usr/local/lib/lua/5.4/socket' && ./test 时,我会和你一样恐慌。

独立的 Lua 二进制文件工作而你的不工作的原因是前者 is linked with -E:

MYLDFLAGS= $(LOCAL) -Wl,-E

ld's documentation for -E 是这样说的:

If you use dlopen to load a dynamic object which needs to refer back to the symbols defined by the program, rather than some other dynamic object, then you will probably need to use this option when linking the program itself.

Lua 使用 dlopen 加载你 require 的 C 模块,并且说模块需要调用 Lua 函数,这些函数链接到你的二进制文件中,所以它您需要此选项是有道理的。事实上,当我将 -Wl,-E 添加到 GCC 命令行时,它对我来说工作正常:

root@077bbb831441:/# gcc -o test main.c /usr/local/lib/liblua.a -ldl -lm -Wl,-rpath='/usr/local/lib/lua/5.4/socket' -Wl,-E && ./test
lua enter
LuaSocket 3.0-rc1
lua exit