Packing shared object in mod for ffi

Hello everyone.
I have the need to run inference on neural networks inside of a vehicle controller. We have decided to write a small library in C to run the models. The library will be loaded with ffi.load. All of our codebase is packaged as a BNG mod.

My issue is that I cannot seem to find the proper path to give ffi for it to find the shared object I have in my mod. An assertion with FS:fileExists shows that the shared object is accessible, but when using the same path in ffi.load I get not found errors.

The only fix I have found is to reference the source shared object (not the one packaged in the mod) with an absolute path.

Is this expected?

Thank you for your help,
Côme

Hi Côme,
ffi.load uses the native operating system path as the argument. This is expected, as the filesystem virtualization we provide exists mainly for untrusted code security, and ffi.load is inherently not secure. If your shared object is located in the BeamNG virtual filesystem (VFS), you can use the FS:virtual2Native('/virtual/path/to/file') function to get the absolute path.

Thank you for your answer!
Do we have access to this method in the VELUA VM? I get this error:
lua/vehicle/controller/xlab/lib/nn.lua:111: attempt to call method ‘virtual2Native’ (a nil value)

    assert(FS:fileExists('lua/vehicle/controller/xlab/lib/libnn.so'))
    libnn = ffi.load(FS:virtual2Native('lua/common/extensions/xlab/libnn.so'))

The function is only available in GELua, but you can use intra-VM communication to send this data to VLua:

GELua:

assert(FS:fileExists('lua/vehicle/controller/xlab/lib/libnn.so'))
local libnnPath = FS:virtual2Native('lua/common/extensions/xlab/libnn.so')
be:sendToMailbox('libnnPath', libnnPath) 

VLua:

local libnnPath = obj:getLastMailbox('libnnPath')
local libnn = ffi.load(libnnPath)

That worked, thank you! But because my mod is still in zip form in the virtual FS I had to copy it to the native FS unzipped:

    local mod_libpath = 'lua/vehicle/controller/xlab/lib/libnn.so'
    local fs_libpath = 'tmp/libnn.so'
    copyfile(mod_libpath, fs_libpath)

    be:sendToMailbox('libnnPath', FS:virtual2Native(fs_libpath))

It’s a bit clunky I guess but it works. If you have something better please do share!

(thanks to @Neverless for the help!)

1 Like

Hello,
I think that is a good solution, the ffi.load function does not have access to the virtual filesystem and therefore cannot access .zip contents. Glad that you got it working :slight_smile: