Luajit 从当前工作目录而不是默认搜索路径加载共享对象

Luajit load shared object from current working directory instead of default search path

我在 Ubuntu 16.04

上使用 Luajit 2.0.4

我有一个简单的 C 库。

int five() {
    return 5;
}

我是这样编译的

gcc -o five.so -shared -fPIC -Wall -Werror five.c

在同一目录中我有一个 lua 脚本

local ffi = require("ffi")

ffi.load("./five.so")

ffi.cdef([[
int five();
]])

print(ffi.C.five())

我也用绝对路径试过。

local ffi = require("ffi")

local fh = assert(io.popen("pwd", "r"))
local cwd = assert(fh:read())

print(cwd)

ffi.load(cwd .. "/five.so")

ffi.cdef([[
int five();
]])

print(ffi.C.five())

当我运行

luajit five.lua

我明白了

luajit: five.lua:6: luajit: undefined symbol: five
stack traceback:
        [C]: in function '__index'
        five.lua:6: in main chunk
        [C]: at 0x004044a0

如何在 luajit 中加载当前工作目录中的共享对象?

没错。原因是 ffi.C 指向一个命名空间以访问标准 C 运行时(加上一些额外的库,具体取决于您的 OS)。来自 LuaJIT 文档:

This is the default C library namespace [...] — note the uppercase 'C'. It binds to the default set of symbols or libraries on the target system. These are more or less the same as a C compiler would offer by default, without specifying extra link libraries.

如果您想从外部库调用 C 函数,您需要:

  1. ffi.cdef 中声明要使用的函数,因此 LuaJIT 知道如何 调用该函数。
  2. 导入外部库并赋值给 一个 Lua 变量,用作外部的命名空间 功能。
  3. 实际调用函数。

您的代码可以改写为:

local ffi = require("ffi")

local lib = ffi.load("five")

ffi.cdef([[
   int five();
]])

print(lib.five())

此外,不需要添加 .os 后缀。要解析库名称,使用 package.cpath 变量。它的工作方式类似于 package.path 变量。问号 (?) 替换为库名称。

$ luajit -e "print(package.cpath)"
./?.so;/usr/local/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/loadall.so