【问题标题】:PANIC: unprotected error in call to Lua API (undefined symbol: lua_gettop)PANIC:调用 Lua API 时出现不受保护的错误(未定义符号:lua_gettop)
【发布时间】:2021-09-06 13:33:55
【问题描述】:

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

错误消息是: PANIC:调用 Lua API 时出现未受保护的错误(错误运行脚本:错误从文件“/usr/local/lib/lua/5.4/socket/core.so”加载模块“socket.core”:未定义符号: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;
}

【问题讨论】:

  • 您是否确定您的 C 程序使用的是正确版本的 Lua,并且您正在正确编译它(即将它与 Lua 正确链接)?
  • Unix 上的 C 扩展模块期望可执行文件重新导出 Lua API。标准解释器通过将 Lua 库与-Wl,-E 标志静态链接来做到这一点。
  • siffiejoe,我是否使用 -Wl,-E 标志构建了 main.c?像这样:“gcc -o test main.c /usr/local/lib/liblua.a -ldl -lm -Wl,rpath='/usr/local/lib/lua/5.4/socket' -E”?跨度>
  • 你好 DarkWiiPlayer,我确定 c 程序使用的是正确的版本,版本是 lua 5.4。
  • 作为一个健全性测试,你能让你的 Lua 脚本做print(_VERSION)吗?

标签: lua luasocket


【解决方案1】:

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

我能够用这个 Dockerfile 重现你的问题:

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' &amp;&amp; ./test 时,我会遇到和你一样的恐慌。

独立的 Lua 二进制文件有效而你的无效的原因是前者is linked with -E

MYLDFLAGS= $(LOCAL) -Wl,-E

ld's documentation for -E 这么说:

如果您使用dlopen 加载需要引用程序定义的符号的动态对象,而不是其他一些动态对象,那么您可能需要在链接程序本身时使用此选项。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-30
    • 2017-05-29
    • 2012-08-14
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    相关资源
    最近更新 更多