链接器错误:疯狂的Python中的lua.require('socket') -> 未定义的符号:lua_getmetatable。

我有一个依赖于一些 lua 文件的 python 项目,其中一个需要 'socket'。当我尝试从 Python 2.7 中要求该 lua 文件时,我会收到加载 socket.core 时出现“未定义符号:lua_getmetatable”的错误。

简单复制者:

$ python
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53)
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import lua
>>> lua.require('socket')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception: error: error loading module 'socket.core' from file
    '/usr/lib/lua/5.1/socket/core.so':
    /usr/lib/lua/5.1/socket/core.so: undefined symbol: lua_getmetatable

我使用的是一个 最近的 Lunatic Python 分支,我已经清除了 Py_ssize_t 警告,并使用 Ubuntu 11.04 上的 liblua5.1-socket2。

如果我使用主要的 lunatic-python 源代码和/或升级到 luasocket 2.0.2,我会得到相同的错误。

编辑:这个错误是什么原因,该如何修复?

编辑#2:这是构建 luasocket-2.0.2 的输出。默认的 make 没有构建 unix.so,我编辑它以构建它,这样我就不会将 2.0.0 与 2.0.2 混合使用:

$ make
cd src; make all
make[1]: Entering directory `/sandbox/luasocket/luasocket-2.0.2/src'
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o luasocket.o luasocket.c
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o timeout.o timeout.c
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o buffer.o buffer.c
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o io.o io.c
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o auxiliar.o auxiliar.c
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o options.o options.c
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o inet.o inet.c
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o tcp.o tcp.c
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o udp.o udp.c
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o except.o except.c
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o select.o select.c
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o usocket.o usocket.c
gcc  -O -shared -fpic -o socket.so.2.0.2 luasocket.o timeout.o buffer.o io.o auxiliar.o options.o inet.o tcp.o udp.o except.o select.o usocket.o
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o mime.o mime.c
gcc  -O -shared -fpic -o mime.so.1.0.2 mime.o
gcc -I/usr/include/lua5.1 -DLUASOCKET_DEBUG  -pedantic -Wall -O2 -fpic -llua   -c -o unix.o unix.c
gcc  -O -shared -fpic -o unix.so buffer.o auxiliar.o options.o timeout.o io.o usocket.o unix.o
make[1]: Leaving directory `/sandbox/luasocket/luasocket-2.0.2/src'

原文链接 https://stackoverflow.com/questions/8361437

点赞
stackoverflow用户221509
stackoverflow用户221509

问题不在 luasocket,而在共享库的符号处理方式上。

问题在于 lua.so(Python 模块)链接到 liblua5.1.so,但通过 require 加载的共享模块无法访问 liblua5.1.so 中的符号。在 Mac OS X 上,这可以正常工作,因为 dlopen 加载的符号默认为 RTLD_GLOBAL

我尝试修改 Lua 源代码(lua-5.1.4/src/loadlib.c:69),但无济于事。因为当 requirelua.so 中调用时,liblua5.1.so 中的符号已经被本地加载到 lua.so 中。这就是为什么 luasocket 无法看到它们的原因。

幸运的是,Python 允许您使用 sys 模块更改 dlopen 语义。这使您可以强制使用 RTLD_GLOBAL 加载模块,这正是所需的。尝试运行以下代码并查看它是否适用于您:

$ python
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53)
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys, DLFCN
>>> sys.setdlopenflags(DLFCN.RTLD_NOW | DLFCN.RTLD_GLOBAL)
>>> import lua
>>> lua.require("socket")
<Lua table at 0x22ccef0>
2011-12-06 16:37:52