Mercurial
view third_party/luajit/doc/ext_ffi.html @ 279:b3b547563ec7
Add Google connector service and agent wiki
Implement the C/Seobeo Google Drive and Gmail connector with encrypted OAuth storage, Zenbu authentication, browser testing, AI tool discovery, chunked HTTP decoding, and Bazel coverage. Consolidate repository guidance into progressive wiki documentation and enforce arena-first allocation for new first-party C code.
Co-authored-by: Copilot <[email protected]>
Copilot-Session: 84c338fd-0939-4bb3-b7f3-1062eb213e5d
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 17 Aug 2026 22:22:36 -0700 |
| parents | 94705b5986b3 |
| children |
line wrap: on
line source
<!DOCTYPE html> <html> <head> <title>FFI Library</title> <meta charset="utf-8"> <meta name="Copyright" content="Copyright (C) 2005-2023"> <meta name="Language" content="en"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> </head> <body> <div id="site"> <a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a> </div> <div id="head"> <h1>FFI Library</h1> </div> <div id="nav"> <ul><li> <a href="luajit.html">LuaJIT</a> <ul><li> <a href="https://luajit.org/download.html">Download <span class="ext">»</span></a> </li><li> <a href="install.html">Installation</a> </li><li> <a href="running.html">Running</a> </li></ul> </li><li> <a href="extensions.html">Extensions</a> <ul><li> <a class="current" href="ext_ffi.html">FFI Library</a> <ul><li> <a href="ext_ffi_tutorial.html">FFI Tutorial</a> </li><li> <a href="ext_ffi_api.html">ffi.* API</a> </li><li> <a href="ext_ffi_semantics.html">FFI Semantics</a> </li></ul> </li><li> <a href="ext_buffer.html">String Buffers</a> </li><li> <a href="ext_jit.html">jit.* Library</a> </li><li> <a href="ext_c_api.html">Lua/C API</a> </li><li> <a href="ext_profiler.html">Profiler</a> </li></ul> </li><li> <a href="https://luajit.org/status.html">Status <span class="ext">»</span></a> </li><li> <a href="https://luajit.org/faq.html">FAQ <span class="ext">»</span></a> </li><li> <a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a> </li></ul> </div> <div id="main"> <p> The FFI library allows <b>calling external C functions</b> and <b>using C data structures</b> from pure Lua code. </p> <p> The FFI library largely obviates the need to write tedious manual Lua/C bindings in C. No need to learn a separate binding language — <b>it parses plain C declarations!</b> These can be cut-n-pasted from C header files or reference manuals. It's up to the task of binding large libraries without the need for dealing with fragile binding generators. </p> <p> 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 is on par with the code a C compiler would generate. Calls to C functions can be inlined in JIT-compiled code, unlike calls to functions bound via the classic Lua/C API. </p> <p> This page gives a short introduction to the usage of the FFI library. <em>Please use the FFI sub-topics in the navigation bar to learn more.</em> </p> <h2 id="call">Motivating Example: Calling External C Functions</h2> <p> It's really easy to call an external C library function: </p> <pre class="code mark"> <span class="codemark">① ② ③</span>local ffi = require("ffi") ffi.cdef[[ <span style="color:#00a000;">int printf(const char *fmt, ...);</span> ]] ffi.C.printf("Hello %s!", "world") </pre> <p> So, let's pick that apart: </p> <p> <span class="mark">①</span> Load the FFI library. </p> <p> <span class="mark">②</span> Add a C declaration for the function. The part inside the double-brackets (in green) is just standard C syntax. </p> <p> <span class="mark">③</span> Call the named C function — Yes, it's that simple! </p> <p style="font-size: 8pt;"> Actually, what goes on behind the scenes is far from simple: <span style="color:#4040c0;">③</span> makes use of the standard C library namespace <tt>ffi.C</tt>. Indexing this namespace with a symbol name (<tt>"printf"</tt>) automatically binds it to the standard C library. The result is a special kind of object which, when called, runs the <tt>printf</tt> function. The arguments passed to this function are automatically converted from Lua objects to the corresponding C types. </p> <p> Ok, so maybe the use of <tt>printf()</tt> wasn't such a spectacular example. You could have done that with <tt>io.write()</tt> and <tt>string.format()</tt>, too. But you get the idea ... </p> <p> So here's something to pop up a message box on Windows: </p> <pre class="code"> local ffi = require("ffi") ffi.cdef[[ <span style="color:#00a000;">int MessageBoxA(void *w, const char *txt, const char *cap, int type);</span> ]] ffi.C.MessageBoxA(nil, "Hello world!", "Test", 0) </pre> <p> Bing! Again, that was far too easy, no? </p> <p style="font-size: 8pt;"> Compare this with the effort required to bind that function using the classic Lua/C API: create an extra C file, add a C function 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 a <tt>luaopen_*</tt> function and register all module functions, compile and link it into a shared library (DLL), move it to the proper path, add Lua code that loads the module aaaand ... finally call the binding function. Phew! </p> <h2 id="cdata">Motivating Example: Using C Data Structures</h2> <p> 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 be used stand-alone, too. </p> <p> Lua is built upon high-level data types. They are flexible, extensible and dynamic. That's why we all love Lua so much. Alas, this can be 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 be implemented with a big table holding lots of tiny tables. This imposes both a substantial memory overhead as well as a performance overhead. </p> <p> Here's a sketch of a library that operates on color images, plus a simple benchmark. First, the plain Lua version: </p> <pre class="code"> local floor = math.floor local 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 img end local function image_to_gray(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 end end local N = 400*400 local img = image_ramp_green(N) for i=1,1000 do image_to_gray(img, N) end </pre> <p> This creates a table with 160.000 pixels, each of which is a table holding four number values in the range of 0-255. First, an image with a green ramp is created (1D for simplicity), then the image is converted to grayscale 1000 times. Yes, that's silly, but I was in need of a simple example ... </p> <p> And here's the FFI version. The modified parts have been marked in bold: </p> <pre class="code mark"> <span class="codemark">① ② ③ ④ ③ ⑤</span><b>local ffi = require("ffi") ffi.cdef[[ </b><span style="color:#00a000;">typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel;</span><b> ]]</b> local function image_ramp_green(n) <b>local img = ffi.new("rgba_pixel[?]", n)</b> local f = 255/(n-1) for i=<b>0,n-1</b> do <b>img[i].green = i*f</b> <b>img[i].alpha = 255</b> end return img end local function image_to_grey(img, n) for i=<b>0,n-1</b> do local y = <b>0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue</b> img[i].red = y; img[i].green = y; img[i].blue = y end end local N = 400*400 local img = image_ramp_green(N) for i=1,1000 do image_to_grey(img, N) end </pre> <p> Ok, so that wasn't too difficult: </p> <p> <span class="mark">①</span> First, load the FFI library and declare the low-level data type. Here we choose a <tt>struct</tt> which holds four byte fields, one for each component of a 4x8 bit RGBA pixel. </p> <p> <span class="mark">②</span> Creating the data structure with <tt>ffi.new()</tt> is straightforward — the <tt>'?'</tt> is a placeholder for the number of elements of a variable-length array. </p> <p> <span class="mark">③</span> C arrays are zero-based, so the indexes have to run from <tt>0</tt> to <tt>n-1</tt>. One might want to allocate one more element instead to simplify converting legacy code. </p> <p> <span class="mark">④</span> Since <tt>ffi.new()</tt> zero-fills the array by default, we only need to set the green and the alpha fields. </p> <p> <span class="mark">⑤</span> The calls to <tt>math.floor()</tt> can be omitted here, because floating-point numbers are already truncated towards zero when converting them to an integer. This happens implicitly when the number is stored in the fields of each pixel. </p> <p> Now let's have a look at the impact of the changes: first, memory consumption for the image is down from 22 Megabytes to 640 Kilobytes (400*400*4 bytes). That's a factor of 35x less! So, yes, tables do have a noticeable overhead. BTW: The original program would consume 40 Megabytes in plain Lua (on x64). </p> <p> Next, performance: the pure Lua version runs in 9.57 seconds (52.9 seconds with the Lua interpreter) and the FFI version runs in 0.48 seconds on my machine (YMMV). That's a factor of 20x faster (110x faster than the Lua interpreter). </p> <p style="font-size: 8pt;"> The avid reader may notice that converting the pure Lua version over to use array indexes for the colors (<tt>[1]</tt> instead of <tt>.red</tt>, <tt>[2]</tt> instead of <tt>.green</tt> etc.) ought to be more compact and faster. This is certainly true (by a factor of ~1.7x). Switching to a struct-of-arrays would help, too. </p> <p style="font-size: 8pt;"> However, the resulting code would be 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 conversion penalties. </p> <br class="flush"> </div> <div id="foot"> <hr class="hide"> Copyright © 2005-2023 <span class="noprint"> · <a href="contact.html">Contact</a> </span> </div> </body> </html>