diff options
author | sanine <sanine.not@pm.me> | 2023-03-11 15:58:20 -0600 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2023-03-11 15:58:20 -0600 |
commit | ebc50b387ab209c9f9a0d92e340ac293d5697274 (patch) | |
tree | ea8c8b3677a18c994d2b9d33dbef3461dcf18113 /libs/luajit-cmake/luajit/doc/ext_ffi.html | |
parent | c2329b4c8258baa9429c77566c9def97d00e96d7 (diff) |
build & link with luajit instead of lua5.1
Diffstat (limited to 'libs/luajit-cmake/luajit/doc/ext_ffi.html')
-rw-r--r-- | libs/luajit-cmake/luajit/doc/ext_ffi.html | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/libs/luajit-cmake/luajit/doc/ext_ffi.html b/libs/luajit-cmake/luajit/doc/ext_ffi.html new file mode 100644 index 0000000..5f1e2d7 --- /dev/null +++ b/libs/luajit-cmake/luajit/doc/ext_ffi.html @@ -0,0 +1,326 @@ +<!DOCTYPE html> +<html> +<head> +<title>FFI Library</title> +<meta charset="utf-8"> +<meta name="Copyright" content="Copyright (C) 2005-2022"> +<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="status.html">Status</a> +</li><li> +<a href="faq.html">FAQ</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-2022 +<span class="noprint"> +· +<a href="contact.html">Contact</a> +</span> +</div> +</body> +</html> |