LuaJIT
FFI Library
The FFI library allows calling external C functions and using C data Structures from pure Lua code.
The FFI library largely obviates the need to write tedious manual lua/c bindings in C. No need to learn a separate binding language- it parses plain C declarations! These can cut-n-pasted from C header files or reference manuals. It's up to the task of a binding large libraries without the need for dealing with fragile binding generators.
The FFI library is tightly integrated into Luajit (it's not available as a separate module). The code generated by the Jit-compiler for accesses to C data structures from Lua code are on par with the code a C compile R would generate. Calls to C functions can is inlined in jit-compiled code, unlike Calls to functions bound via the classic lua/c API.
This page gives a short introduction to the usage of the FFI library. Please use the FFI sub-topics in the navigation bar to learn more.
Motivating example:calling External C Functions
It ' s really easy-to-call an external C library function:
①②③local FFI = require ("FFI") ffi.cdef[[int printf (const char *fmt, ...);] Ffi. c.printf ("Hello%s!", "World")
So, let's pick that apart:
① Load the FFI library.
② ADD a C declaration for the function. The part inside the double-brackets (in green) are just standard C syntax.
③ Call the named C Function-yes, it's that simple!
Actually, what goes on behind the scenes was far from simple: ③ makes use of the standard C library namespace FFI. C. Indexing this namespace with a symbol name ("printf") automatically binds it to the standard C library. The result is a special kind of object which, when called, runs the printf function. The arguments passed to this function is automatically converted from Lua objects to the corresponding C types.
Ok, so maybe the use of printf () wasn ' t such a spectacular example. You could has done so with Io.write () and String.Format (), too. But I get the idea ...
So here's something to pops up a message box on Windows:
Local FFI = require ("FFI") Ffi.cdef[[int messageboxa (void *w, const char *txt, const char *cap, int type);] Ffi. C.messageboxa (Nil, "Hello world!", "Test", 0)
bing! Again, that's far too easy, no?
Compare this and the effort required to bind the function using the classic lua/c api:create an extra C file, add a C F Unction that retrieves and checks the argument types passed from Lua and calls the actual C function, add a list of module Functions and their names, add aluaopen_* function and register all module functions, compile and link it into a shared l Ibrary (DLL), move it to the proper path, add Lua code that loads the module Aaaand ... finally call the binding function. phew!
Motivating example:using C Data structures
The FFI library allows you to create and access C data structures. Of course the main use for this is for interfacing with C functions. But they can used stand-alone, too.
Lua is built upon high-level data types. They is flexible, extensible and dynamic. That's why we're all love Lua so much. Alas, this can is inefficient for certain tasks, where you ' d really want a low-level data type. e.g. a large array of a fixed structure needs to BES implemented with a big table holding lots of tiny tables. This imposes both a substantial memory overhead as well as a performance overhead.
Here's a sketch of a library that operates in color images plus a simple benchmark. First, the plain Lua version:
local floor = math.floorlocal function image_ramp_green (n)  LOCAL IMG = {}  LOCAL F = 255/(n-1) for i=1,n do img[i] = { red = 0, green = floor ((i-1 ) *f), blue = 0, alpha = 255 } end return Imgendlocal function image_to_grey (img, n) for i=1,n do local y = floor (0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue ) img[i].red = y; img[i].green = y; img[i].blue = y endendlocal n = 400*400local img = image_ramp_green (N) for i=1,1000 do image_to_grey (img, n) End
This creates a table with 160.000 pixels, each of the which are a table holding four number values in the range of 0-255. First an image with a green ramp are created (1D for simplicity) and then the image is converted to greyscale times. Yes, that's silly, but I am in need of a simple example ...
And here ' s the FFI version. The modified parts has been marked in bold:
①②③④③⑤local ffi = require ("Ffi") ffi.cdef[[typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel;]] Local function image_ramp_green (n) local img = ffi.new ("rgba_pixel[?]", n) local f = 255/(n-1) for i=0,n-1 do img[i].green = i*f img[i].alpha = 255 end return imgendlocal function image_to_grey (img, n) for i=0,n-1 do local y = 0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue img[i].red = y; img[i].green = y; img[i] . blue = y endendlocal n = 400*400local img = image_ramp_ Green (N) For i=1,1000 do image_to_grey (img, n) End
Ok, so that wasn ' t too difficult:
① First, load the FFI library and declare the low-level data type. Here we choose astruct which holds four bytes fields, one for each component of a 4x8 bit RGBA pixel.
② Creating The data structure with ffi.new () are straightforward-the '? ' is a placeholder for the number of Elem Ents of a variable-length array.
③ C arrays is zero-based, so the indexes has to run from 0 to n-1. One might want to allocate one more element instead to simplify converting legacy code.
④ Since ffi.new () zero-fills the array by default, we only need to set the green and the alpha fields.
⑤ The calls to Math.floor () can is omitted here, because floating-point numbers is already truncated towards Zer o when the converting them to an integer. This happens implicitly if the number is stored in the fields of each pixel.
Now let's has a look at the impact of the Changes:first, memory consumption for the image was down from megabytes to 6 Kilobytes (400*400*4 bytes). That ' s a factor of 35x less! So, yes, tables does have a noticeable overhead. Btw:the original program would consume, megabytes in plain Lua (on x64).
Next, Performance:the Pure Lua version runs in 9.57 seconds (52.9 seconds with the Lua interpreter) and the FFI version R Uns in 0.48 seconds on my machine (YMMV). That ' s a factor of 20x faster (110x faster than the LUA interpreter).
The avid reader may notice this converting the pure Lua version over to use array indexes for the colors ([1] instead of. Red, [2] instead. Green etc.) Ought to is more compact and faster. This is certainly true (by a factor of ~1.7x). Switching to a struct-of-arrays would help, too.
However the resulting code would is less idiomatic and rather error-prone. And it still doesn ' t get even close to the performance of the FFI version of the code. Also, high-level data structures cannot be easily passed to other C functions, especially I/O functions, without undue con Version penalties.
Luajit FFI Library