mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 15:14:08 +00:00
FFI: Add preliminary FFI documentation (still incomplete).
This commit is contained in:
parent
8396c3cdbc
commit
e985aeda84
@ -271,7 +271,10 @@ img.right {
|
|||||||
color: #2142bf;
|
color: #2142bf;
|
||||||
}
|
}
|
||||||
#nav ul ul a {
|
#nav ul ul a {
|
||||||
padding: 0 1em 0 2em;
|
padding: 0 1em 0 1.7em;
|
||||||
|
}
|
||||||
|
#nav ul ul ul a {
|
||||||
|
padding: 0 0.5em 0 2.4em;
|
||||||
}
|
}
|
||||||
#main {
|
#main {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
@ -30,6 +30,17 @@ div.major { max-width: 600px; padding: 1em; margin: 1em 0 1em 0; }
|
|||||||
</li><li>
|
</li><li>
|
||||||
<a href="extensions.html">Extensions</a>
|
<a href="extensions.html">Extensions</a>
|
||||||
<ul><li>
|
<ul><li>
|
||||||
|
<a 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_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
|
@ -27,6 +27,17 @@
|
|||||||
</li><li>
|
</li><li>
|
||||||
<a href="extensions.html">Extensions</a>
|
<a href="extensions.html">Extensions</a>
|
||||||
<ul><li>
|
<ul><li>
|
||||||
|
<a 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_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
|
@ -27,6 +27,17 @@
|
|||||||
</li><li>
|
</li><li>
|
||||||
<a href="extensions.html">Extensions</a>
|
<a href="extensions.html">Extensions</a>
|
||||||
<ul><li>
|
<ul><li>
|
||||||
|
<a 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_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a class="current" href="ext_c_api.html">Lua/C API</a>
|
<a class="current" href="ext_c_api.html">Lua/C API</a>
|
||||||
|
280
doc/ext_ffi.html
Normal file
280
doc/ext_ffi.html
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>FFI Library</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="Author" content="Mike Pall">
|
||||||
|
<meta name="Copyright" content="Copyright (C) 2005-2011, Mike Pall">
|
||||||
|
<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="http://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="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_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="status.html">Status</a>
|
||||||
|
<ul><li>
|
||||||
|
<a href="changes.html">Changes</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="faq.html">FAQ</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||||
|
</li><li>
|
||||||
|
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||||
|
</li></ul>
|
||||||
|
</div>
|
||||||
|
<div id="main">
|
||||||
|
<p>
|
||||||
|
The FFI library allows calling external C functions and the use
|
||||||
|
of C data structures from pure Lua code.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The FFI library largely obviates the need to write tedious manual
|
||||||
|
Lua/C bindings in C. It doesn't require learning a separate binding
|
||||||
|
language — it parses plain C declarations, which 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 the 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.
|
||||||
|
Please use the FFI sub-topics in the navigation bar to learn more.
|
||||||
|
</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">
|
||||||
|
<span style="color:#000080;">local ffi = require("ffi")</span>
|
||||||
|
ffi.cdef[[
|
||||||
|
<span style="color:#00a000;font-weight:bold;">int printf(const char *fmt, ...);</span>
|
||||||
|
]]
|
||||||
|
<span style="color:#c06000;font-weight:bold;">ffi.C</span>.printf("Hello %s!", "world")
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
So, let's pick that apart: the first line (in blue) loads the FFI
|
||||||
|
library. The next one adds a C declaration for the function. The
|
||||||
|
part between the double-brackets (in green) is just standard
|
||||||
|
C syntax. And the last line calls 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: the first
|
||||||
|
part of the last line (in orange) 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 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[[
|
||||||
|
int MessageBoxA(void *w, const char *txt, const char *cap, int type);
|
||||||
|
]]
|
||||||
|
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="call">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_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
|
||||||
|
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>
|
||||||
|
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 greyscale 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">
|
||||||
|
<b>local ffi = require("ffi")
|
||||||
|
ffi.cdef[[
|
||||||
|
typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel;
|
||||||
|
]]</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: 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>
|
||||||
|
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. C arrays are zero-based, so the
|
||||||
|
indexes have to run from <tt>0</tt> to <tt>n-1</tt> (one might
|
||||||
|
allocate one more element instead to simplify converting legacy
|
||||||
|
code). Since <tt>ffi.new()</tt> zero-fills the array by default, we
|
||||||
|
only need to set the green and the alpha fields.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
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 with plain Lua).
|
||||||
|
</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), but 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-2011 Mike Pall
|
||||||
|
<span class="noprint">
|
||||||
|
·
|
||||||
|
<a href="contact.html">Contact</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
410
doc/ext_ffi_api.html
Normal file
410
doc/ext_ffi_api.html
Normal file
@ -0,0 +1,410 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>ffi.* API Functions</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="Author" content="Mike Pall">
|
||||||
|
<meta name="Copyright" content="Copyright (C) 2005-2011, Mike Pall">
|
||||||
|
<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">
|
||||||
|
<style type="text/css">
|
||||||
|
table.abitable { width: 30em; line-height: 1.2; }
|
||||||
|
tr.abihead td { font-weight: bold; }
|
||||||
|
td.abiparam { font-weight: bold; width: 6em; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="site">
|
||||||
|
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||||
|
</div>
|
||||||
|
<div id="head">
|
||||||
|
<h1><tt>ffi.*</tt> API Functions</h1>
|
||||||
|
</div>
|
||||||
|
<div id="nav">
|
||||||
|
<ul><li>
|
||||||
|
<a href="luajit.html">LuaJIT</a>
|
||||||
|
<ul><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 href="ext_ffi.html">FFI Library</a>
|
||||||
|
<ul><li>
|
||||||
|
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
|
||||||
|
</li><li>
|
||||||
|
<a class="current" href="ext_ffi_api.html">ffi.* API</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="status.html">Status</a>
|
||||||
|
<ul><li>
|
||||||
|
<a href="changes.html">Changes</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="faq.html">FAQ</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||||
|
</li><li>
|
||||||
|
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||||
|
</li></ul>
|
||||||
|
</div>
|
||||||
|
<div id="main">
|
||||||
|
<p>
|
||||||
|
This page describes the API functions provided by the FFI library in
|
||||||
|
detail. It's recommended to read through the
|
||||||
|
<a href="ext_ffi.html">introduction</a> and the
|
||||||
|
<a href="ext_ffi_tutorial.html">FFI tutorial</a> first.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="glossary">Glossary</h2>
|
||||||
|
<ul>
|
||||||
|
<li><b>cdecl</b> — An abstract C type declaration (a Lua
|
||||||
|
string).</li>
|
||||||
|
<li><b>ctype</b> — A C type object. This is a special kind of
|
||||||
|
<b>cdata</b> returned by <tt>ffi.typeof()</tt>. It serves as a
|
||||||
|
<b>cdata</b> <a href="#ffi_new">constructor</a> when called.</li>
|
||||||
|
<li><b>cdata</b> — A C data object. It holds a value of the
|
||||||
|
corresponding <b>ctype</b>.</li>
|
||||||
|
<li><b>ct</b> — A C type specification which can be used for
|
||||||
|
most of the API functions. Either a <b>cdecl</b>, a <b>ctype</b> or a
|
||||||
|
<b>cdata</b> serving as a template type.</li>
|
||||||
|
<li><b>VLA</b> — A variable-length array is declared with a
|
||||||
|
<tt>?</tt> instead of the number of elements, e.g. <tt>"int[?]"</tt>.
|
||||||
|
The number of elements (<tt>nelem</tt>) must be given when it's
|
||||||
|
<a href="#ffi_new">created</a>.</li>
|
||||||
|
<li><b>VLS</b> — A variable-length struct is a <tt>struct</tt> C
|
||||||
|
type where the last element is a <b>VLA</b>. The same rules for
|
||||||
|
declaration and creation apply.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 id="decl">Declaring and Accessing External Symbols</h2>
|
||||||
|
<p>
|
||||||
|
External symbols must be declared first and can then be accessed by
|
||||||
|
indexing a <a href="ext_ffi_semantics.html#clib">C library
|
||||||
|
namespace</a>, which automatically binds the symbol to a specific
|
||||||
|
library.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="ffi_cdef"><tt>ffi.cdef(def)</tt></h3>
|
||||||
|
<p>
|
||||||
|
Adds multiple C declarations for types or external symbols (named
|
||||||
|
variables or functions). <tt>def</tt> must be a Lua string. It's
|
||||||
|
recommended to use the syntactic sugar for string arguments as
|
||||||
|
follows:
|
||||||
|
</p>
|
||||||
|
<pre class="code">
|
||||||
|
ffi.cdef[[
|
||||||
|
<span style="color:#00a000;font-weight:bold;">typedef struct foo { int a, b; } foo_t; // Declare a struct and typedef.
|
||||||
|
int dofoo(foo_t *f, int n); /* Declare an external C function. */</span>
|
||||||
|
]]
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The contents of the string (the part in green above) must be a
|
||||||
|
sequence of
|
||||||
|
<a href="ext_ffi_semantics.html#clang">C declarations</a>,
|
||||||
|
separated by semicolons. The trailing semicolon for a single
|
||||||
|
declaration may be omitted.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Please note that external symbols are only <em>declared</em>, but they
|
||||||
|
are <em>not bound</em> to any specific address, yet. Binding is
|
||||||
|
achieved with C library namespaces (see below).
|
||||||
|
</p>
|
||||||
|
<p style="color: #c00000;">
|
||||||
|
C declarations are not passed through a C pre-processor,
|
||||||
|
yet. No pre-processor tokens are allowed, except for
|
||||||
|
<tt>#pragma pack</tt>. Replace <tt>#define</tt> in existing
|
||||||
|
C header files with <tt>enum</tt>, <tt>static const</tt>
|
||||||
|
or <tt>typedef</tt> and/or pass the files through an external
|
||||||
|
C pre-processor (once). Be careful not to include unneeded or
|
||||||
|
redundant declarations from unrelated header files.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="ffi_C"><tt>ffi.C</tt></h3>
|
||||||
|
<p>
|
||||||
|
This is the default C library namespace — note the
|
||||||
|
uppercase <tt>'C'</tt>. It binds to the default set of symbols or
|
||||||
|
libraries on the target system. These are more or less the same as a
|
||||||
|
C compiler would offer by default, without specifying extra link
|
||||||
|
libraries.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
On POSIX systems, this binds to symbols in the default or global
|
||||||
|
namespace. This includes all exported symbols from the executable and
|
||||||
|
any libraries loaded into the global namespace. This includes at least
|
||||||
|
<tt>libc</tt>, <tt>libm</tt>, <tt>libdl</tt> (on Linux),
|
||||||
|
<tt>libgcc</tt> (if compiled with GCC), as well as any exported
|
||||||
|
symbols from the Lua/C API provided by LuaJIT itself.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
On Windows systems, this binds to symbols exported from the
|
||||||
|
<tt>*.exe</tt>, the <tt>lua51.dll</tt> (i.e. the Lua/C API
|
||||||
|
provided by LuaJIT itself), the C runtime library LuaJIT was linked
|
||||||
|
with (<tt>msvcrt*.dll</tt>), <tt>kernel32.dll</tt>,
|
||||||
|
<tt>user32.dll</tt> and <tt>gdi32.dll</tt>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="ffi_load"><tt>clib = ffi.load(name [,global])</tt></h3>
|
||||||
|
<p>
|
||||||
|
This loads the dynamic library given by <tt>name</tt> and returns
|
||||||
|
a new C library namespace which binds to its symbols. On POSIX
|
||||||
|
systems, if <tt>global</tt> is <tt>true</tt>, the library symbols are
|
||||||
|
loaded into the global namespace, too.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If <tt>name</tt> is a path, the library is loaded from this path.
|
||||||
|
Otherwise <tt>name</tt> is canonicalized in a system-dependent way and
|
||||||
|
searched in the default search path for dynamic libraries:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
On POSIX systems, if the name contains no dot, the extension
|
||||||
|
<tt>.so</tt> is appended. Also, the <tt>lib</tt> prefix is prepended
|
||||||
|
if necessary. So <tt>ffi.load("z")</tt> looks for <tt>"libz.so"</tt>
|
||||||
|
in the default shared library search path.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
On Windows systems, if the name contains no dot, the extension
|
||||||
|
<tt>.dll</tt> is appended. So <tt>ffi.load("ws2_32")</tt> looks for
|
||||||
|
<tt>"ws2_32.dll"</tt> in the default DLL search path.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="create">Creating cdata Objects</h2>
|
||||||
|
<p>
|
||||||
|
The following API functions create cdata objects (<tt>type()</tt>
|
||||||
|
returns <tt>"cdata"</tt>). All created cdata objects are
|
||||||
|
<a href="ext_ffi_semantics.html#gc">garbage collected</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="ffi_new"><tt>cdata = ffi.new(ct [,nelem] [,init...])<br>
|
||||||
|
cdata = <em>ctype</em>([nelem,] [init...])</tt></h3>
|
||||||
|
<p>
|
||||||
|
Creates a cdata object for the given <tt>ct</tt>. VLA/VLS types
|
||||||
|
require the <tt>nelem</tt> argument. The second syntax uses a ctype as
|
||||||
|
a constructor and is otherwise fully equivalent.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The <tt>init</tt> arguments provide optional initializers. The created
|
||||||
|
cdata object is filled with zero bytes if no initializers are given.
|
||||||
|
Scalar types accept a single initializer. Aggregates can either be
|
||||||
|
initialized with a flat list of initializers or a single aggregate
|
||||||
|
initializer (see the <a href="ext_ffi_semantics.html#convert">C type
|
||||||
|
conversion rules</a>). Excess initializers cause an error.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If a single initializer is given for an array, it's repeated for all
|
||||||
|
remaining elements. This doesn't happen if two or more initializers
|
||||||
|
are given — all uninitialized elements are filled with zero
|
||||||
|
bytes. The fields of a <tt>struct</tt> are initialized in the order of
|
||||||
|
their declaration. Uninitialized fields are filled with zero bytes.
|
||||||
|
Only the first field of <tt>union</tt> can be initialized with a flat
|
||||||
|
initializer. Elements or fields which are aggregates themselves are
|
||||||
|
initialized with a <em>single</em> <tt>init</tt> argument, but this
|
||||||
|
may be an aggregate initializer of course.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Performance notice: if you want to create many objects of one kind,
|
||||||
|
parse the cdecl only once and get its ctype with
|
||||||
|
<tt>ffi.typeof()</tt>. Then use the ctype as a constructor repeatedly.
|
||||||
|
</p>
|
||||||
|
<p style="font-size: 8pt;">
|
||||||
|
Please note that an anonymous <tt>struct</tt> declaration implicitly
|
||||||
|
creates a new and distinguished ctype every time you use it for
|
||||||
|
<tt>ffi.new()</tt>. This is probably <b>not</b> what you want,
|
||||||
|
especially if you create more than one cdata object. Different anonymous
|
||||||
|
<tt>structs</tt> are not considered assignment-compatible by the
|
||||||
|
C standard, even though they may have the same fields! Also, they
|
||||||
|
are considered different types by the JIT-compiler, which may cause an
|
||||||
|
excessive number of traces. It's strongly suggested to either declare
|
||||||
|
a named <tt>struct</tt> or <tt>typedef</tt> with <tt>ffi.cdef()</tt>
|
||||||
|
or to create a single ctype object for an anonymous <tt>struct</tt>
|
||||||
|
with <tt>ffi.typeof()</tt>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="ffi_typeof"><tt>ctype = ffi.typeof(ct)</tt></h3>
|
||||||
|
<p>
|
||||||
|
Creates a ctype object for the given <tt>ct</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This function is especially useful to parse a cdecl only once and then
|
||||||
|
use the resulting ctype object as a <a href="#ffi_new">constructor</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="ffi_cast"><tt>cdata = ffi.cast(ct, init)</tt></h3>
|
||||||
|
<p>
|
||||||
|
Creates a scalar cdata object for the given <tt>ct</tt>. The cdata
|
||||||
|
object is initialized with <tt>init</tt> using the "cast" variant of
|
||||||
|
the <a href="ext_ffi_semantics.html#convert">C type conversion
|
||||||
|
rules</a>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This functions is mainly useful to override the pointer compatibility
|
||||||
|
rules or to convert pointers to addresses or vice versa. For maximum
|
||||||
|
portability you should convert a pointer to its address as follows:
|
||||||
|
</p>
|
||||||
|
<pre class="code">
|
||||||
|
local addr = tonumber(ffi.cast("intptr_t", ptr))
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="info">C Type Information</h2>
|
||||||
|
<p>
|
||||||
|
The following API functions return information about C types.
|
||||||
|
They are most useful for inspecting cdata objects.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="ffi_sizeof"><tt>size = ffi.sizeof(ct [,nelem])</tt></h3>
|
||||||
|
<p>
|
||||||
|
Returns the size of <tt>ct</tt> in bytes. Returns <tt>nil</tt> if
|
||||||
|
the size is not known (e.g. for <tt>"void"</tt> or function types).
|
||||||
|
Requires <tt>nelem</tt> for VLA/VLS types, except for cdata objects.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="ffi_alignof"><tt>align = ffi.alignof(ct)</tt></h3>
|
||||||
|
<p>
|
||||||
|
Returns the minimum required alignment for <tt>ct</tt> in bytes.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="ffi_offsetof"><tt>ofs [,bpos,bsize] = ffi.offsetof(ct, field)</tt></h3>
|
||||||
|
<p>
|
||||||
|
Returns the offset (in bytes) of <tt>field</tt> relative to the start
|
||||||
|
of <tt>ct</tt>, which must be a <tt>struct</tt>. Additionally returns
|
||||||
|
the position and the field size (in bits) for bit fields.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="util">Utility Functions</h2>
|
||||||
|
|
||||||
|
<h3 id="ffi_string"><tt>str = ffi.string(ptr [,len])</tt></h3>
|
||||||
|
<p>
|
||||||
|
Creates an interned Lua string from the data pointed to by
|
||||||
|
<tt>ptr</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If the optional argument <tt>len</tt> is missing, <tt>ptr</tt> is
|
||||||
|
converted to a <tt>"char *"</tt> and the data is assumed to be
|
||||||
|
zero-terminated. The length of the string is computed with
|
||||||
|
<tt>strlen()</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Otherwise <tt>ptr</tt> is converted to a <tt>"void *"</tt> and
|
||||||
|
<tt>len</tt> gives the length of the data. The data may contain
|
||||||
|
embedded zeros and need not be byte-oriented (though this may cause
|
||||||
|
endianess issues).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This function is mainly useful to convert (temporary)
|
||||||
|
<tt>"const char *"</tt> pointers returned by
|
||||||
|
C functions to Lua strings and store them or pass them to other
|
||||||
|
functions expecting a Lua string. The Lua string is an (interned) copy
|
||||||
|
of the data and bears no relation to the original data area anymore.
|
||||||
|
Lua strings are 8 bit clean and may be used to hold arbitrary,
|
||||||
|
non-character data.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Performance notice: it's faster to pass the length of the string, if
|
||||||
|
it's known. E.g. when the length is returned by a C call like
|
||||||
|
<tt>sprintf()</tt>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="ffi_copy"><tt>ffi.copy(dst, src, len)<br>
|
||||||
|
ffi.copy(dst, str)</tt></h3>
|
||||||
|
<p>
|
||||||
|
Copies the data pointed to by <tt>src</tt> to <tt>dst</tt>.
|
||||||
|
<tt>dst</tt> is converted to a <tt>"void *"</tt> and <tt>src</tt>
|
||||||
|
is converted to a <tt>"const void *"</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In the first syntax, <tt>len</tt> gives the number of bytes to copy.
|
||||||
|
In case <tt>src</tt> is a Lua string, the maximum copy length is the
|
||||||
|
number of bytes of the string plus a zero-terminator. Caveat: the
|
||||||
|
copied data may not be zero-terminated if <tt>len ≤ #src</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In the second syntax, the source of the copy must be a Lua string. All
|
||||||
|
bytes of the string plus a zero-terminator are copied to <tt>dst</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Performance notice: <tt>ffi.copy()</tt> may be used as a faster
|
||||||
|
(inlineable) replacement for the C library functions
|
||||||
|
<tt>memcpy()</tt>, <tt>strcpy()</tt> and <tt>strncpy()</tt>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="ffi_fill"><tt>ffi.fill(dst, len [,c])</tt></h3>
|
||||||
|
<p>
|
||||||
|
Fills the data pointed to by <tt>dst</tt> with <tt>len</tt> constant
|
||||||
|
bytes, given by <tt>c</tt>. If <tt>c</tt> is omitted, the data is
|
||||||
|
zero-filled.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Performance notice: <tt>ffi.fill()</tt> may be used as a faster
|
||||||
|
(inlineable) replacement for the C library function
|
||||||
|
<tt>memset(dst, c, len)</tt>. Please note the different
|
||||||
|
order of arguments!
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="target">Target-specific Information</h2>
|
||||||
|
|
||||||
|
<h3 id="ffi_abi"><tt>status = ffi.abi(param)</tt></h3>
|
||||||
|
<p>
|
||||||
|
Returns <tt>true</tt> if <tt>param</tt> (a Lua string) applies for the
|
||||||
|
target ABI (Application Binary Interface). Otherwise returns
|
||||||
|
<tt>false</tt>. The following parameters are currently defined:
|
||||||
|
</p>
|
||||||
|
<table class="abitable">
|
||||||
|
<tr class="abihead">
|
||||||
|
<td class="abiparam">Parameter</td>
|
||||||
|
<td class="abidesc">Description</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd separate">
|
||||||
|
<td class="abiparam">32bit</td><td class="abidesc">32 bit architecture</td></tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td class="abiparam">64bit</td><td class="abidesc">64 bit architecture</td></tr>
|
||||||
|
<tr class="odd separate">
|
||||||
|
<td class="abiparam">le</td><td class="abidesc">Little-endian architecture</td></tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td class="abiparam">be</td><td class="abidesc">Big-endian architecture</td></tr>
|
||||||
|
<tr class="odd separate">
|
||||||
|
<td class="abiparam">fpu</td><td class="abidesc">Target has a hardware FPU</td></tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td class="abiparam">softfp</td><td class="abidesc">softfp calling conventions</td></tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td class="abiparam">hardfp</td><td class="abidesc">hardfp calling conventions</td></tr>
|
||||||
|
<tr class="even separate">
|
||||||
|
<td class="abiparam">eabi</td><td class="abidesc">EABI variant of the standard ABI</td></tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td class="abiparam">win</td><td class="abidesc">Windows variant of the standard ABI</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3 id="ffi_os"><tt>ffi.os</tt></h3>
|
||||||
|
<p>
|
||||||
|
Contains the target OS name. Same contents as
|
||||||
|
<a href="ext_jit.html#jit_os"><tt>jit.os</tt></a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="ffi_arch"><tt>ffi.arch</tt></h3>
|
||||||
|
<p>
|
||||||
|
Contains the target architecture name. Same contents as
|
||||||
|
<a href="ext_jit.html#jit_arch"><tt>jit.arch</tt></a>.
|
||||||
|
</p>
|
||||||
|
<br class="flush">
|
||||||
|
</div>
|
||||||
|
<div id="foot">
|
||||||
|
<hr class="hide">
|
||||||
|
Copyright © 2005-2011 Mike Pall
|
||||||
|
<span class="noprint">
|
||||||
|
·
|
||||||
|
<a href="contact.html">Contact</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
73
doc/ext_ffi_int64.html
Normal file
73
doc/ext_ffi_int64.html
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>64 bit Integers</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="Author" content="Mike Pall">
|
||||||
|
<meta name="Copyright" content="Copyright (C) 2005-2011, Mike Pall">
|
||||||
|
<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="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||||
|
</div>
|
||||||
|
<div id="head">
|
||||||
|
<h1>64 bit Integers</h1>
|
||||||
|
</div>
|
||||||
|
<div id="nav">
|
||||||
|
<ul><li>
|
||||||
|
<a href="luajit.html">LuaJIT</a>
|
||||||
|
<ul><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 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 class="current" href="ext_ffi_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="status.html">Status</a>
|
||||||
|
<ul><li>
|
||||||
|
<a href="changes.html">Changes</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="faq.html">FAQ</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||||
|
</li><li>
|
||||||
|
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||||
|
</li></ul>
|
||||||
|
</div>
|
||||||
|
<div id="main">
|
||||||
|
<p>
|
||||||
|
TODO
|
||||||
|
</p>
|
||||||
|
<br class="flush">
|
||||||
|
</div>
|
||||||
|
<div id="foot">
|
||||||
|
<hr class="hide">
|
||||||
|
Copyright © 2005-2011 Mike Pall
|
||||||
|
<span class="noprint">
|
||||||
|
·
|
||||||
|
<a href="contact.html">Contact</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
155
doc/ext_ffi_semantics.html
Normal file
155
doc/ext_ffi_semantics.html
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>FFI Semantics</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="Author" content="Mike Pall">
|
||||||
|
<meta name="Copyright" content="Copyright (C) 2005-2011, Mike Pall">
|
||||||
|
<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="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||||
|
</div>
|
||||||
|
<div id="head">
|
||||||
|
<h1>FFI Semantics</h1>
|
||||||
|
</div>
|
||||||
|
<div id="nav">
|
||||||
|
<ul><li>
|
||||||
|
<a href="luajit.html">LuaJIT</a>
|
||||||
|
<ul><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 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_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a class="current" href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="status.html">Status</a>
|
||||||
|
<ul><li>
|
||||||
|
<a href="changes.html">Changes</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="faq.html">FAQ</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||||
|
</li><li>
|
||||||
|
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||||
|
</li></ul>
|
||||||
|
</div>
|
||||||
|
<div id="main">
|
||||||
|
<p>
|
||||||
|
TODO
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="clang">C Language Support</h2>
|
||||||
|
<p>
|
||||||
|
TODO
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="convert">C Type Conversion Rules</h2>
|
||||||
|
<p>
|
||||||
|
TODO
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="clib">C Library Namespaces</h2>
|
||||||
|
<p>
|
||||||
|
A C library namespace is a special kind of object which allows
|
||||||
|
access to the symbols contained in libraries. Indexing it with a
|
||||||
|
symbol name (a Lua string) automatically binds it to the library.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
TODO
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="ops">Operations on cdata Objects</h2>
|
||||||
|
<p>
|
||||||
|
TODO
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="gc">Garbage Collection of cdata Objects</h2>
|
||||||
|
<p>
|
||||||
|
All explicitly (<tt>ffi.new()</tt> etc.) or implicitly (accessors)
|
||||||
|
created cdata objects are garbage collected. You need to ensure to
|
||||||
|
retain valid references to cdata objects somewhere on a Lua stack, an
|
||||||
|
upvalue or in a Lua table while they are still in use. Once the last
|
||||||
|
reference to a cdata object is gone, the garbage collector will
|
||||||
|
automatically free the memory used by it (at the end of the next GC
|
||||||
|
cycle).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Please note that pointers themselves are cdata objects, however they
|
||||||
|
are <b>not</b> followed by the garbage collector. So e.g. if you
|
||||||
|
assign a cdata array to a pointer, you must keep the cdata object
|
||||||
|
holding the array alive as long as the pointer is still in use:
|
||||||
|
</p>
|
||||||
|
<pre class="code">
|
||||||
|
ffi.cdef[[
|
||||||
|
typedef struct { int *a; } foo_t;
|
||||||
|
]]
|
||||||
|
|
||||||
|
local s = ffi.new("foo_t", ffi.new("int[10]")) -- <span style="color:#c00000;">WRONG!</span>
|
||||||
|
|
||||||
|
local a = ffi.new("int[10]") -- <span style="color:#00a000;">OK</span>
|
||||||
|
local s = ffi.new("foo_t", a)
|
||||||
|
-- Now do something with 's', but keep 'a' alive until you're done.
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Similar rules apply for Lua strings which are implicitly converted to
|
||||||
|
<tt>"const char *"</tt>: the string object itself must be
|
||||||
|
referenced somewhere or it'll be garbage collected eventually. The
|
||||||
|
pointer will then point to stale data, which may have already beeen
|
||||||
|
overwritten. Note that string literals are automatically kept alive as
|
||||||
|
long as the function containing it (actually its prototype) is not
|
||||||
|
garbage collected.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Objects which are passed as an argument to an external C function
|
||||||
|
are kept alive until the call returns. So it's generally safe to
|
||||||
|
create temporary cdata objects in argument lists. This is a common
|
||||||
|
idiom for passing specific C types to vararg functions:
|
||||||
|
</p>
|
||||||
|
<pre class="code">
|
||||||
|
ffi.cdef[[
|
||||||
|
int printf(const char *fmt, ...);
|
||||||
|
]]
|
||||||
|
ffi.C.printf("integer value: %d\n", ffi.new("int", x)) -- <span style="color:#00a000;">OK</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Memory areas returned by C functions (e.g. from <tt>malloc()</tt>)
|
||||||
|
must be manually managed of course. Pointers to cdata objects are
|
||||||
|
indistinguishable from pointers returned by C functions (which is one
|
||||||
|
of the reasons why the GC cannot follow them).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>TODO</h2>
|
||||||
|
<br class="flush">
|
||||||
|
</div>
|
||||||
|
<div id="foot">
|
||||||
|
<hr class="hide">
|
||||||
|
Copyright © 2005-2011 Mike Pall
|
||||||
|
<span class="noprint">
|
||||||
|
·
|
||||||
|
<a href="contact.html">Contact</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
91
doc/ext_ffi_tutorial.html
Normal file
91
doc/ext_ffi_tutorial.html
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>FFI Tutorial</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="Author" content="Mike Pall">
|
||||||
|
<meta name="Copyright" content="Copyright (C) 2005-2011, Mike Pall">
|
||||||
|
<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="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||||
|
</div>
|
||||||
|
<div id="head">
|
||||||
|
<h1>FFI Tutorial</h1>
|
||||||
|
</div>
|
||||||
|
<div id="nav">
|
||||||
|
<ul><li>
|
||||||
|
<a href="luajit.html">LuaJIT</a>
|
||||||
|
<ul><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 href="ext_ffi.html">FFI Library</a>
|
||||||
|
<ul><li>
|
||||||
|
<a class="current" 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_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="status.html">Status</a>
|
||||||
|
<ul><li>
|
||||||
|
<a href="changes.html">Changes</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="faq.html">FAQ</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||||
|
</li><li>
|
||||||
|
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||||
|
</li></ul>
|
||||||
|
</div>
|
||||||
|
<div id="main">
|
||||||
|
<p>
|
||||||
|
TODO
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="load">Loading the FFI Library</h2>
|
||||||
|
<p>
|
||||||
|
The FFI library is built into LuaJIT by default, but it's not loaded
|
||||||
|
and initialized by default. The suggested way to use the FFI library
|
||||||
|
is to add the following to the start of every Lua file that needs one
|
||||||
|
of its functions:
|
||||||
|
</p>
|
||||||
|
<pre class="code">
|
||||||
|
local ffi = require("ffi")
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Please note this doesn't define an <tt>ffi</tt> variable in the table
|
||||||
|
of globals — you really need to use the local variable. The
|
||||||
|
<tt>require</tt> function ensures the library is only loaded once.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>TODO</h2>
|
||||||
|
<br class="flush">
|
||||||
|
</div>
|
||||||
|
<div id="foot">
|
||||||
|
<hr class="hide">
|
||||||
|
Copyright © 2005-2011 Mike Pall
|
||||||
|
<span class="noprint">
|
||||||
|
·
|
||||||
|
<a href="contact.html">Contact</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -27,6 +27,17 @@
|
|||||||
</li><li>
|
</li><li>
|
||||||
<a href="extensions.html">Extensions</a>
|
<a href="extensions.html">Extensions</a>
|
||||||
<ul><li>
|
<ul><li>
|
||||||
|
<a 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_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
<a class="current" href="ext_jit.html">jit.* Library</a>
|
<a class="current" href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@ -46,8 +57,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<p>
|
<p>
|
||||||
The functions in this built-in module control the behavior
|
The functions in this built-in module control the behavior of the JIT
|
||||||
of the JIT compiler engine.
|
compiler engine. Note that JIT-compilation is fully automatic —
|
||||||
|
you probably won't need to use any of the following functions unless
|
||||||
|
you have special needs.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="jit_onoff"><tt>jit.on()<br>
|
<h3 id="jit_onoff"><tt>jit.on()<br>
|
||||||
|
@ -44,6 +44,17 @@ td.excinterop {
|
|||||||
</li><li>
|
</li><li>
|
||||||
<a class="current" href="extensions.html">Extensions</a>
|
<a class="current" href="extensions.html">Extensions</a>
|
||||||
<ul><li>
|
<ul><li>
|
||||||
|
<a 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_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@ -114,6 +125,13 @@ This way you can use bit operations from both Lua and LuaJIT on a
|
|||||||
shared installation.
|
shared installation.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h3 id="ffi"><tt>ffi.*</tt> — FFI library</h3>
|
||||||
|
<p>
|
||||||
|
The <a href="ext_ffi.html">FFI library</a> allows calling external
|
||||||
|
C functions and the use of C data structures from pure Lua
|
||||||
|
code.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="jit"><tt>jit.*</tt> — JIT compiler control</h3>
|
<h3 id="jit"><tt>jit.*</tt> — JIT compiler control</h3>
|
||||||
<p>
|
<p>
|
||||||
The functions in this module
|
The functions in this module
|
||||||
|
11
doc/faq.html
11
doc/faq.html
@ -30,6 +30,17 @@ dd { margin-left: 1.5em; }
|
|||||||
</li><li>
|
</li><li>
|
||||||
<a href="extensions.html">Extensions</a>
|
<a href="extensions.html">Extensions</a>
|
||||||
<ul><li>
|
<ul><li>
|
||||||
|
<a 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_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
|
@ -56,6 +56,17 @@ td.compatno {
|
|||||||
</li><li>
|
</li><li>
|
||||||
<a href="extensions.html">Extensions</a>
|
<a href="extensions.html">Extensions</a>
|
||||||
<ul><li>
|
<ul><li>
|
||||||
|
<a 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_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
|
@ -28,6 +28,17 @@
|
|||||||
</li><li>
|
</li><li>
|
||||||
<a href="extensions.html">Extensions</a>
|
<a href="extensions.html">Extensions</a>
|
||||||
<ul><li>
|
<ul><li>
|
||||||
|
<a 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_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
|
@ -49,6 +49,17 @@ td.param_default {
|
|||||||
</li><li>
|
</li><li>
|
||||||
<a href="extensions.html">Extensions</a>
|
<a href="extensions.html">Extensions</a>
|
||||||
<ul><li>
|
<ul><li>
|
||||||
|
<a 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_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
|
@ -30,6 +30,17 @@ ul li { padding-bottom: 0.3em; }
|
|||||||
</li><li>
|
</li><li>
|
||||||
<a href="extensions.html">Extensions</a>
|
<a href="extensions.html">Extensions</a>
|
||||||
<ul><li>
|
<ul><li>
|
||||||
|
<a 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_int64.html">64 bit Integers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@ -84,7 +95,7 @@ especially when they contain lengthy debug output or if you require
|
|||||||
confidentiality.
|
confidentiality.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
The JIT compiler only generates code for CPUs with support for
|
The x86 JIT compiler only generates code for CPUs with support for
|
||||||
<b>SSE2</b> instructions. I.e. you need at least a P4, Core 2/i3/i5/i7,
|
<b>SSE2</b> instructions. I.e. you need at least a P4, Core 2/i3/i5/i7,
|
||||||
Atom or K8/K10 to get the full benefit.<br>
|
Atom or K8/K10 to get the full benefit.<br>
|
||||||
If you run LuaJIT on older CPUs without SSE2 support, the JIT compiler
|
If you run LuaJIT on older CPUs without SSE2 support, the JIT compiler
|
||||||
@ -129,7 +140,7 @@ demonstrable need is shown.
|
|||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
The <b>JIT compiler</b> is not complete (yet) and falls back to the
|
The <b>JIT compiler</b> falls back to the
|
||||||
interpreter in some cases. All of this works transparently, so unless
|
interpreter in some cases. All of this works transparently, so unless
|
||||||
you use <tt>-jv</tt>, you'll probably never notice (the interpreter is
|
you use <tt>-jv</tt>, you'll probably never notice (the interpreter is
|
||||||
<a href="http://luajit.org/performance.html"><span class="ext">»</span> quite fast</a>, too). Here are the known issues:
|
<a href="http://luajit.org/performance.html"><span class="ext">»</span> quite fast</a>, too). Here are the known issues:
|
||||||
@ -221,7 +232,7 @@ commented, many basic design decisions are in need of an explanation.
|
|||||||
The rather un-traditional compiler architecture and the many highly
|
The rather un-traditional compiler architecture and the many highly
|
||||||
optimized data structures are a barrier for outside participation in
|
optimized data structures are a barrier for outside participation in
|
||||||
the development. Alas, as I've repeatedly stated, I'm better at
|
the development. Alas, as I've repeatedly stated, I'm better at
|
||||||
writing code than papers and I'm not in need of any academical merits.
|
writing code than papers and I'm not in need of any academic merits.
|
||||||
Someday I will find the time for it. :-)
|
Someday I will find the time for it. :-)
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@ -232,15 +243,6 @@ price of a major redesign of the compiler. This would also pave the
|
|||||||
way for emitting predicated instructions, which is a prerequisite
|
way for emitting predicated instructions, which is a prerequisite
|
||||||
for efficient <b>vectorization</b>.
|
for efficient <b>vectorization</b>.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
Currently Lua is missing a standard library for access to <b>structured
|
|
||||||
binary data</b> and <b>arrays/buffers</b> holding low-level data types.
|
|
||||||
Allowing calls to arbitrary C functions (<b>FFI</b>) would obviate the
|
|
||||||
need to write manual bindings. A variety of Lua extension modules are
|
|
||||||
available, with different scope and capabilities. Alas, none of them has been
|
|
||||||
designed with a JIT compiler in mind. An FFI for LuaJIT is currently
|
|
||||||
in the design phase, but there's no ETA, yet.
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<br class="flush">
|
<br class="flush">
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user