C LuaJIT FFI未从可执行文件加载符号

C LuaJIT FFI未从可执行文件加载符号,c,lua,shared-libraries,ffi,luajit,C,Lua,Shared Libraries,Ffi,Luajit,第一个Lua代码: local ffi = require "ffi" ffi.cdef[[ void printc(const char *fmt, ...); ]] ffi.C.printc("Hello world") local ffi = require "ffi" lib = ffi.load("./build/a.so") ffi.cdef[[ void printc(const char *fmt, ...); ]] lib.printc("Hello world") 不起

第一个Lua代码:

local ffi = require "ffi"

ffi.cdef[[
void printc(const char *fmt, ...);
]]
ffi.C.printc("Hello world")
local ffi = require "ffi"
lib = ffi.load("./build/a.so")
ffi.cdef[[
void printc(const char *fmt, ...);
]]
lib.printc("Hello world")
不起作用。错误:

boot.lua:6: /usr/lib64/libluajit-5.1.so.2: undefined symbol: printc
但是,符号实际上是在LuaJIT运行的可执行文件中定义的(函数声明是从C复制粘贴的):

我对解决方案的第一个想法是使用与可执行文件相同的符号构建一个共享库,并将其加载到LuaJIT中:

$ cc -fPIC -shared $LDFLAGS $OFILES -o build/a.so
新Lua代码:

local ffi = require "ffi"

ffi.cdef[[
void printc(const char *fmt, ...);
]]
ffi.C.printc("Hello world")
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从正在运行的可执行文件加载符号?

-rdynamic
标志传递给
cc
解决了这个问题,允许LuaJIT从程序运行
FFI.C.
函数。

不是专家,但是,请尝试
objdump-t./build/a.out
并查看该符号是否存在于可执行文件中:)您可能需要在链接时使用
-Wl,-E
从可执行文件中导出符号。@DarkWiiPlayer这就是
nm--仅定义的
。下面是
objdump-t build/a.out | grep printc
000000000001abd1 g F.text 0000000000000179 printc
使用
-E
的建议不起作用,但它让我找到了
-rdynamic
标志,它确实解决了问题;DR对此答案的基本原理,^F表示“导出动态”。当指定-rdynamic时,gcc在链接期间将此选项传递给ld(/collect2)。