【发布时间】:2023-03-27 01:41:01
【问题描述】:
第一个 Lua 代码:
local ffi = require "ffi"
ffi.cdef[[
void printc(const char *fmt, ...);
]]
ffi.C.printc("Hello world")
不起作用。错误:
boot.lua:6: /usr/lib64/libluajit-5.1.so.2: undefined symbol: printc
然而,这个符号实际上是在运行 LuaJIT 的可执行文件中定义的(并且函数声明是从 C 复制粘贴的):
$ nm --defined-only build/a.out | grep printc
00000000000650c1 T printc
我对解决方案的第一个想法是构建一个与可执行文件具有相同符号的共享库,并将其加载到 LuaJIT 中:
$ cc -fPIC -shared $LDFLAGS $OFILES -o build/a.so
新的 Lua 代码:
local ffi = require "ffi"
lib = ffi.load("./build/a.so")
ffi.cdef[[
void printc(const char *fmt, ...);
]]
lib.printc("Hello world")
这允许我调用printc 函数。但是,有一个非常大的问题:加载的库使用与正在运行的程序分开的内存空间。lib.printc("Hello world") 正在写入的缓冲区与运行 LuaJIT 的程序不同的缓冲区用途。它就像在与一个完全不同的过程进行交互一样。
printc 应该打印到运行 LuaJIT 的可执行文件的控制台子系统。控制台缓冲区存储为一个全局 (extern) 字符串数组,printc 将写入该数组。 LuaJIT 通过加载 a.so 获得的全局控制台缓冲区指向其他内存地址,而不是正在运行的 a.out 程序的全局控制台缓冲区。
所以这不是一个可行的解决方案。我不知道我现在该怎么办。这些符号作为我的可执行文件的一部分被导出,但 LuaJIT 没有加载它们。我也不能ffi.load我的可执行文件:
lib = ffi.load("./build/a.out")
boot.lua:2: ./build/a.out: cannot dynamically load position-independent executable
如何让 LuaJIT FFI 从我正在运行的可执行文件中加载符号?
【问题讨论】:
-
不是专家,但请尝试
objdump -t ./build/a.out看看该符号是否甚至存在于可执行文件中:) -
您可能需要在链接时使用
-Wl,-E从可执行文件中导出符号。 -
@DarkWiiPlayer 这就是
nm --defined-only does。这里是objdump -t build/a.out| grep printc:000000000001abd1 g F .text 0000000000000179 printc -
使用
-E的建议不起作用,但它让我找到了解决问题的-rdynamic标志。
标签: c lua shared-libraries ffi luajit