Luajit FFI Library

Source: Internet
Author: User
Tags ffi

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.