Greg Nisbet
Greg Nisbet

Reputation: 6994

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

I'm using Luajit 2.0.4 on Ubuntu 16.04

I have a simple C library.

int five() {
    return 5;
}

I compile it like so

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

In the same directory I have a lua script

local ffi = require("ffi")

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

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

print(ffi.C.five())

I've also tried it with an absolute path.

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())

When I run

luajit five.lua

I get this

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

How do I load a shared object in the current working directory in luajit?

Upvotes: 2

Views: 3331

Answers (1)

Diego Pino
Diego Pino

Reputation: 11586

That's correct. The reason is that ffi.C points to a namespace to access the standard C-runtime (plus some additional libraries depending on your OS). From LuaJIT docs:

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.

If you want to call a C-function from an external library you need to:

  1. Declare the function to use inside ffi.cdef, so LuaJIT knows how to call that function.
  2. Import the external library and assign it to a Lua variable which serves as a namespace for the external function.
  3. Actually call the function.

Your code can be reworked as:

local ffi = require("ffi")

local lib = ffi.load("five")

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

print(lib.five())

In addition, it's not necessary to add .os suffix. To resolve library names, the package.cpath variable is used. It works like package.path variable. Question marks (?) are replaced by the library name.

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

Upvotes: 3

Related Questions