mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 15:14:08 +00:00
Cleanup of docs.
This commit is contained in:
parent
a5aade2fa9
commit
1f0006ac71
@ -256,7 +256,7 @@ to avoid joining by the compiler/linker.</li>
|
|||||||
<li>Merged with Lua 5.1.1. Fixes all
|
<li>Merged with Lua 5.1.1. Fixes all
|
||||||
<a href="http://www.lua.org/bugs.html#5.1"><span class="ext">»</span> known bugs in Lua 5.1</a>.</li>
|
<a href="http://www.lua.org/bugs.html#5.1"><span class="ext">»</span> known bugs in Lua 5.1</a>.</li>
|
||||||
<li>Enforce (dynamic) linker error for EXE/DLL version mismatches.</li>
|
<li>Enforce (dynamic) linker error for EXE/DLL version mismatches.</li>
|
||||||
<li>Minor changes to DynASM: faster preprocessing, smaller encoding
|
<li>Minor changes to DynASM: faster pre-processing, smaller encoding
|
||||||
for some immediates.</li>
|
for some immediates.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
|
@ -8,6 +8,12 @@
|
|||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
|
<style type="text/css">
|
||||||
|
span.codemark { position:absolute; left: 16em; color: #4040c0; }
|
||||||
|
span.mark { color: #4040c0; font-family: Courier New, Courier, monospace;
|
||||||
|
line-height: 1.1; }
|
||||||
|
pre.mark { padding-left: 2em; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<div id="site">
|
||||||
@ -55,16 +61,20 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<p>
|
<p>
|
||||||
The FFI library allows calling external C functions and the use
|
|
||||||
of C data structures from pure Lua code.
|
The FFI library allows <b>calling external C functions</b> and
|
||||||
|
<b>using C data structures</b> from pure Lua code.
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
The FFI library largely obviates the need to write tedious manual
|
The FFI library largely obviates the need to write tedious manual
|
||||||
Lua/C bindings in C. It doesn't require learning a separate binding
|
Lua/C bindings in C. No need to learn a separate binding language
|
||||||
language — it parses plain C declarations, which can be
|
— <b>it parses plain C declarations!</b> These can be
|
||||||
cut-n-pasted from C header files or reference manuals. It's up to
|
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
|
the task of binding large libraries without the need for dealing with
|
||||||
fragile binding generators.
|
fragile binding generators.
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The FFI library is tightly integrated into LuaJIT (it's not available
|
The FFI library is tightly integrated into LuaJIT (it's not available
|
||||||
@ -83,26 +93,30 @@ Please use the FFI sub-topics in the navigation bar to learn more.
|
|||||||
<p>
|
<p>
|
||||||
It's really easy to call an external C library function:
|
It's really easy to call an external C library function:
|
||||||
</p>
|
</p>
|
||||||
<pre class="code">
|
<pre class="code mark">
|
||||||
local ffi = require("ffi") <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">①</span>
|
<span class="codemark">①
|
||||||
ffi.cdef[[ <span style="color:#f0f4ff;">//</span><span style="color:#4040c0;">②</span>
|
②
|
||||||
|
|
||||||
|
|
||||||
|
③</span>local ffi = require("ffi")
|
||||||
|
ffi.cdef[[
|
||||||
<span style="color:#00a000;">int printf(const char *fmt, ...);</span>
|
<span style="color:#00a000;">int printf(const char *fmt, ...);</span>
|
||||||
]]
|
]]
|
||||||
ffi.C.printf("Hello %s!", "world") <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">③</span>
|
ffi.C.printf("Hello %s!", "world")
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
So, let's pick that apart:
|
So, let's pick that apart:
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">①</span> Load the FFI library.
|
<span class="mark">①</span> Load the FFI library.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">②</span> Add a C declaration
|
<span class="mark">②</span> Add a C declaration
|
||||||
for the function. The part inside the double-brackets (in green) is
|
for the function. The part inside the double-brackets (in green) is
|
||||||
just standard C syntax.
|
just standard C syntax.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">③</span> Call the named
|
<span class="mark">③</span> Call the named
|
||||||
C function — Yes, it's that simple!
|
C function — Yes, it's that simple!
|
||||||
</p>
|
</p>
|
||||||
<p style="font-size: 8pt;">
|
<p style="font-size: 8pt;">
|
||||||
@ -198,25 +212,42 @@ need of a simple example ...
|
|||||||
And here's the FFI version. The modified parts have been marked in
|
And here's the FFI version. The modified parts have been marked in
|
||||||
bold:
|
bold:
|
||||||
</p>
|
</p>
|
||||||
<pre class="code">
|
<pre class="code mark">
|
||||||
<b>local ffi = require("ffi")</b> <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">①</span>
|
<span class="codemark">①
|
||||||
<b>ffi.cdef[[
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
②
|
||||||
|
|
||||||
|
③
|
||||||
|
④
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
③
|
||||||
|
⑤</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><span style="color:#00a000;">typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel;</span><b>
|
||||||
]]</b>
|
]]</b>
|
||||||
|
|
||||||
local function image_ramp_green(n)
|
local function image_ramp_green(n)
|
||||||
<b>local img = ffi.new("rgba_pixel[?]", n)</b> <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">②</span>
|
<b>local img = ffi.new("rgba_pixel[?]", n)</b>
|
||||||
local f = 255/(n-1)
|
local f = 255/(n-1)
|
||||||
for i=<b>0,n-1</b> do <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">③</span>
|
for i=<b>0,n-1</b> do
|
||||||
<b>img[i].green = i*f</b> <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">④</span>
|
<b>img[i].green = i*f</b>
|
||||||
<b>img[i].alpha = 255</b>
|
<b>img[i].alpha = 255</b>
|
||||||
end
|
end
|
||||||
return img
|
return img
|
||||||
end
|
end
|
||||||
|
|
||||||
local function image_to_grey(img, n)
|
local function image_to_grey(img, n)
|
||||||
for i=<b>0,n-1</b> do <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">③</span>
|
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> <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">⑤</span>
|
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
|
img[i].red = y; img[i].green = y; img[i].blue = y
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -231,30 +262,30 @@ end
|
|||||||
Ok, so that wasn't too difficult:
|
Ok, so that wasn't too difficult:
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">①</span> First, load the FFI
|
<span class="mark">①</span> First, load the FFI
|
||||||
library and declare the low-level data type. Here we choose a
|
library and declare the low-level data type. Here we choose a
|
||||||
<tt>struct</tt> which holds four byte fields, one for each component
|
<tt>struct</tt> which holds four byte fields, one for each component
|
||||||
of a 4x8 bit RGBA pixel.
|
of a 4x8 bit RGBA pixel.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">②</span> Creating the data
|
<span class="mark">②</span> Creating the data
|
||||||
structure with <tt>ffi.new()</tt> is straightforward — the
|
structure with <tt>ffi.new()</tt> is straightforward — the
|
||||||
<tt>'?'</tt> is a placeholder for the number of elements of a
|
<tt>'?'</tt> is a placeholder for the number of elements of a
|
||||||
variable-length array.
|
variable-length array.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">③</span> C arrays are
|
<span class="mark">③</span> C arrays are
|
||||||
zero-based, so the indexes have to run from <tt>0</tt> to
|
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
|
<tt>n-1</tt>. One might want to allocate one more element instead to
|
||||||
simplify converting legacy code.
|
simplify converting legacy code.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">④</span> Since <tt>ffi.new()</tt>
|
<span class="mark">④</span> Since <tt>ffi.new()</tt>
|
||||||
zero-fills the array by default, we only need to set the green and the
|
zero-fills the array by default, we only need to set the green and the
|
||||||
alpha fields.
|
alpha fields.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">⑤</span> The calls to
|
<span class="mark">⑤</span> The calls to
|
||||||
<tt>math.floor()</tt> can be omitted here, because floating-point
|
<tt>math.floor()</tt> can be omitted here, because floating-point
|
||||||
numbers are already truncated towards zero when converting them to an
|
numbers are already truncated towards zero when converting them to an
|
||||||
integer. This happens implicitly when the number is stored in the
|
integer. This happens implicitly when the number is stored in the
|
||||||
|
@ -316,7 +316,7 @@ bytes of the string <em>plus a zero-terminator</em> are copied to
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Performance notice: <tt>ffi.copy()</tt> may be used as a faster
|
Performance notice: <tt>ffi.copy()</tt> may be used as a faster
|
||||||
(inlineable) replacement for the C library functions
|
(inlinable) replacement for the C library functions
|
||||||
<tt>memcpy()</tt>, <tt>strcpy()</tt> and <tt>strncpy()</tt>.
|
<tt>memcpy()</tt>, <tt>strcpy()</tt> and <tt>strncpy()</tt>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@ -328,7 +328,7 @@ zero-filled.
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Performance notice: <tt>ffi.fill()</tt> may be used as a faster
|
Performance notice: <tt>ffi.fill()</tt> may be used as a faster
|
||||||
(inlineable) replacement for the C library function
|
(inlinable) replacement for the C library function
|
||||||
<tt>memset(dst, c, len)</tt>. Please note the different
|
<tt>memset(dst, c, len)</tt>. Please note the different
|
||||||
order of arguments!
|
order of arguments!
|
||||||
</p>
|
</p>
|
||||||
|
@ -66,9 +66,9 @@ and its interaction with both Lua and C code.
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Given that the FFI library is designed to interface with C code
|
Given that the FFI library is designed to interface with C code
|
||||||
and that declarations can be written in plain C syntax, it
|
and that declarations can be written in plain C syntax, <b>it
|
||||||
closely follows the C language semantics, wherever possible. Some
|
closely follows the C language semantics</b>, wherever possible.
|
||||||
minor concessions are needed for smoother interoperation with Lua
|
Some minor concessions are needed for smoother interoperation with Lua
|
||||||
language semantics.
|
language semantics.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@ -83,9 +83,8 @@ background.
|
|||||||
Please note: this is the first public release of the FFI library. This
|
Please note: this is the first public release of the FFI library. This
|
||||||
does not comprise the final specification for the FFI semantics, yet.
|
does not comprise the final specification for the FFI semantics, yet.
|
||||||
Some of the semantics may need to be changed, based on feedback from
|
Some of the semantics may need to be changed, based on feedback from
|
||||||
developers. Please <a href="contact.html">report</a> any problems
|
developers. Please <a href="contact.html">report</a> any problems you
|
||||||
you've encountered or any improvements you'd like to see — thank
|
may encounter or any improvements you'd like to see — thank you!
|
||||||
you!
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 id="clang">C Language Support</h2>
|
<h2 id="clang">C Language Support</h2>
|
||||||
@ -204,7 +203,7 @@ The following C features are <b>not</b> supported:
|
|||||||
default to an <tt>int</tt> type.</li>
|
default to an <tt>int</tt> type.</li>
|
||||||
|
|
||||||
<li>Old-style empty function declarations (K&R) are not allowed.
|
<li>Old-style empty function declarations (K&R) are not allowed.
|
||||||
All C functions must have a proper protype declaration. A
|
All C functions must have a proper prototype declaration. A
|
||||||
function declared without parameters (<tt>int foo();</tt>) is
|
function declared without parameters (<tt>int foo();</tt>) is
|
||||||
treated as a function taking zero arguments, like in C++.</li>
|
treated as a function taking zero arguments, like in C++.</li>
|
||||||
|
|
||||||
@ -312,7 +311,7 @@ C type of the destination, the
|
|||||||
are applied.
|
are applied.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Reference types are immutable after initialization ("no reseating of
|
Reference types are immutable after initialization ("no re-seating of
|
||||||
references"). For initialization purposes or when passing values to
|
references"). For initialization purposes or when passing values to
|
||||||
reference parameters, they are treated like pointers. Note that unlike
|
reference parameters, they are treated like pointers. Note that unlike
|
||||||
in C++, there's no way to implement automatic reference generation of
|
in C++, there's no way to implement automatic reference generation of
|
||||||
@ -652,8 +651,8 @@ variable argument part of vararg C function use
|
|||||||
<a href="#convert_vararg">special conversion rules</a>. This
|
<a href="#convert_vararg">special conversion rules</a>. This
|
||||||
C function is called and the return value (if any) is
|
C function is called and the return value (if any) is
|
||||||
<a href="#convert_tolua">converted to a Lua object</a>.<br>
|
<a href="#convert_tolua">converted to a Lua object</a>.<br>
|
||||||
On Windows/x86 systems, <tt>stdcall</tt> functions are automatically
|
On Windows/x86 systems, <tt>__stdcall</tt> functions are automatically
|
||||||
detected and a function declared as <tt>cdecl</tt> (the default) is
|
detected and a function declared as <tt>__cdecl</tt> (the default) is
|
||||||
silently fixed up after the first call.</li>
|
silently fixed up after the first call.</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
@ -790,7 +789,7 @@ local s = ffi.new("foo_t", a)
|
|||||||
Similar rules apply for Lua strings which are implicitly converted to
|
Similar rules apply for Lua strings which are implicitly converted to
|
||||||
<tt>"const char *"</tt>: the string object itself must be
|
<tt>"const char *"</tt>: the string object itself must be
|
||||||
referenced somewhere or it'll be garbage collected eventually. The
|
referenced somewhere or it'll be garbage collected eventually. The
|
||||||
pointer will then point to stale data, which may have already beeen
|
pointer will then point to stale data, which may have already been
|
||||||
overwritten. Note that <em>string literals</em> are automatically kept
|
overwritten. Note that <em>string literals</em> are automatically kept
|
||||||
alive as long as the function containing it (actually its prototype)
|
alive as long as the function containing it (actually its prototype)
|
||||||
is not garbage collected.
|
is not garbage collected.
|
||||||
@ -951,7 +950,7 @@ storing and initializing them are supported, yet.</li>
|
|||||||
<li>The <tt>volatile</tt> type qualifier is currently ignored by
|
<li>The <tt>volatile</tt> type qualifier is currently ignored by
|
||||||
compiled code.</li>
|
compiled code.</li>
|
||||||
<li><a href="ext_ffi_api.html#ffi_cdef"><tt>ffi.cdef</tt></a> silently
|
<li><a href="ext_ffi_api.html#ffi_cdef"><tt>ffi.cdef</tt></a> silently
|
||||||
ignores all redeclarations.</li>
|
ignores all re-declarations.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
The JIT compiler already handles a large subset of all FFI operations.
|
The JIT compiler already handles a large subset of all FFI operations.
|
||||||
|
@ -9,7 +9,12 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
|
span.codemark { position:absolute; left: 16em; color: #4040c0; }
|
||||||
|
span.mark { color: #4040c0; font-family: Courier New, Courier, monospace;
|
||||||
|
line-height: 1.1; }
|
||||||
|
pre.mark { padding-left: 2em; }
|
||||||
table.idiomtable { line-height: 1.2; }
|
table.idiomtable { line-height: 1.2; }
|
||||||
|
table.idiomtable tt { font-size: 100%; }
|
||||||
tr.idiomhead td { font-weight: bold; }
|
tr.idiomhead td { font-weight: bold; }
|
||||||
td.idiomc { width: 12em; }
|
td.idiomc { width: 12em; }
|
||||||
td.idiomlua { width: 14em; }
|
td.idiomlua { width: 14em; }
|
||||||
@ -94,27 +99,46 @@ The following code explains how to access standard system functions.
|
|||||||
We slowly print two lines of dots by sleeping for 10 milliseconds
|
We slowly print two lines of dots by sleeping for 10 milliseconds
|
||||||
after each dot:
|
after each dot:
|
||||||
</p>
|
</p>
|
||||||
<pre class="code">
|
<pre class="code mark">
|
||||||
local ffi = require("ffi")
|
<span class="codemark">
|
||||||
ffi.cdef[[ <span style="color:#f0f4ff;">//</span><span style="color:#4040c0;">①</span>
|
①
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
②
|
||||||
|
③
|
||||||
|
④
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
⑤
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
⑥</span>local ffi = require("ffi")
|
||||||
|
ffi.cdef[[
|
||||||
<span style="color:#00a000;">void Sleep(int ms);
|
<span style="color:#00a000;">void Sleep(int ms);
|
||||||
int poll(struct pollfd *fds, unsigned long nfds, int timeout);</span>
|
int poll(struct pollfd *fds, unsigned long nfds, int timeout);</span>
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local sleep
|
local sleep
|
||||||
if ffi.os == "Windows" then <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">②</span>
|
if ffi.os == "Windows" then
|
||||||
function sleep(s) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">③</span>
|
function sleep(s)
|
||||||
ffi.C.Sleep(s*1000) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">④</span>
|
ffi.C.Sleep(s*1000)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
function sleep(s)
|
function sleep(s)
|
||||||
ffi.C.poll(nil, 0, s*1000) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">⑤</span>
|
ffi.C.poll(nil, 0, s*1000)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for i=1,160 do
|
for i=1,160 do
|
||||||
io.write("."); io.flush()
|
io.write("."); io.flush()
|
||||||
sleep(0.01) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">⑥</span>
|
sleep(0.01)
|
||||||
end
|
end
|
||||||
io.write("\n")
|
io.write("\n")
|
||||||
</pre>
|
</pre>
|
||||||
@ -122,14 +146,14 @@ io.write("\n")
|
|||||||
Here's the step-by-step explanation:
|
Here's the step-by-step explanation:
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">①</span> This defines the
|
<span class="mark">①</span> This defines the
|
||||||
C library functions we're going to use. The part inside the
|
C library functions we're going to use. The part inside the
|
||||||
double-brackets (in green) is just standard C syntax. You can
|
double-brackets (in green) is just standard C syntax. You can
|
||||||
usually get this info from the C header files or the
|
usually get this info from the C header files or the
|
||||||
documentation provided by each C library or C compiler.
|
documentation provided by each C library or C compiler.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">②</span> The difficulty we're
|
<span class="mark">②</span> The difficulty we're
|
||||||
facing here, is that there are different standards to choose from.
|
facing here, is that there are different standards to choose from.
|
||||||
Windows has a simple <tt>Sleep()</tt> function. On other systems there
|
Windows has a simple <tt>Sleep()</tt> function. On other systems there
|
||||||
are a variety of functions available to achieve sub-second sleeps, but
|
are a variety of functions available to achieve sub-second sleeps, but
|
||||||
@ -139,14 +163,14 @@ check for <tt>ffi.os</tt> makes sure we use the Windows-specific
|
|||||||
function only on Windows systems.
|
function only on Windows systems.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">③</span> Here we're wrapping the
|
<span class="mark">③</span> Here we're wrapping the
|
||||||
call to the C function in a Lua function. This isn't strictly
|
call to the C function in a Lua function. This isn't strictly
|
||||||
necessary, but it's helpful to deal with system-specific issues only
|
necessary, but it's helpful to deal with system-specific issues only
|
||||||
in one part of the code. The way we're wrapping it ensures the check
|
in one part of the code. The way we're wrapping it ensures the check
|
||||||
for the OS is only done during initialization and not for every call.
|
for the OS is only done during initialization and not for every call.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">④</span> A more subtle point is
|
<span class="mark">④</span> A more subtle point is
|
||||||
that we defined our <tt>sleep()</tt> function (for the sake of this
|
that we defined our <tt>sleep()</tt> function (for the sake of this
|
||||||
example) as taking the number of seconds, but accepting fractional
|
example) as taking the number of seconds, but accepting fractional
|
||||||
seconds. Multiplying this by 1000 gets us milliseconds, but that still
|
seconds. Multiplying this by 1000 gets us milliseconds, but that still
|
||||||
@ -165,7 +189,7 @@ FFI library automatically detects <tt>stdcall</tt> functions, so you
|
|||||||
don't need to declare them as such.
|
don't need to declare them as such.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">⑤</span> The <tt>poll()</tt>
|
<span class="mark">⑤</span> The <tt>poll()</tt>
|
||||||
function takes a couple more arguments we're not going to use. You can
|
function takes a couple more arguments we're not going to use. You can
|
||||||
simply use <tt>nil</tt> to pass a <tt>NULL</tt> pointer and <tt>0</tt>
|
simply use <tt>nil</tt> to pass a <tt>NULL</tt> pointer and <tt>0</tt>
|
||||||
for the <tt>nfds</tt> parameter. Please note that the
|
for the <tt>nfds</tt> parameter. Please note that the
|
||||||
@ -182,7 +206,7 @@ with this, as it's performed automatically and it's carefully designed
|
|||||||
to bridge the semantic differences between Lua and C.
|
to bridge the semantic differences between Lua and C.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">⑥</span> Now that we have defined
|
<span class="mark">⑥</span> Now that we have defined
|
||||||
our own <tt>sleep()</tt> function, we can just call it from plain Lua
|
our own <tt>sleep()</tt> function, we can just call it from plain Lua
|
||||||
code. That wasn't so bad, huh? Turning these boring animated dots into
|
code. That wasn't so bad, huh? Turning these boring animated dots into
|
||||||
a fascinating best-selling game is left as an exercise for the reader.
|
a fascinating best-selling game is left as an exercise for the reader.
|
||||||
@ -196,27 +220,54 @@ href="http://zlib.net/">zlib</a> compression library from Lua code.
|
|||||||
We'll define two convenience wrapper functions that take a string and
|
We'll define two convenience wrapper functions that take a string and
|
||||||
compress or uncompress it to another string:
|
compress or uncompress it to another string:
|
||||||
</p>
|
</p>
|
||||||
<pre class="code">
|
<pre class="code mark">
|
||||||
local ffi = require("ffi")
|
<span class="codemark">
|
||||||
ffi.cdef[[ <span style="color:#f0f4ff;">//</span><span style="color:#4040c0;">①</span>
|
①
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
②
|
||||||
|
|
||||||
|
|
||||||
|
③
|
||||||
|
|
||||||
|
④
|
||||||
|
|
||||||
|
|
||||||
|
⑤
|
||||||
|
|
||||||
|
|
||||||
|
⑥
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
⑦</span>local ffi = require("ffi")
|
||||||
|
ffi.cdef[[
|
||||||
<span style="color:#00a000;">unsigned long compressBound(unsigned long sourceLen);
|
<span style="color:#00a000;">unsigned long compressBound(unsigned long sourceLen);
|
||||||
int compress2(uint8_t *dest, unsigned long *destLen,
|
int compress2(uint8_t *dest, unsigned long *destLen,
|
||||||
const uint8_t *source, unsigned long sourceLen, int level);
|
const uint8_t *source, unsigned long sourceLen, int level);
|
||||||
int uncompress(uint8_t *dest, unsigned long *destLen,
|
int uncompress(uint8_t *dest, unsigned long *destLen,
|
||||||
const uint8_t *source, unsigned long sourceLen);</span>
|
const uint8_t *source, unsigned long sourceLen);</span>
|
||||||
]]
|
]]
|
||||||
local zlib = ffi.load(ffi.os == "Windows" and "zlib1" or "z") <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">②</span>
|
local zlib = ffi.load(ffi.os == "Windows" and "zlib1" or "z")
|
||||||
|
|
||||||
local function compress(txt)
|
local function compress(txt)
|
||||||
local n = zlib.compressBound(#txt) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">③</span>
|
local n = zlib.compressBound(#txt)
|
||||||
local buf = ffi.new("uint8_t[?]", n)
|
local buf = ffi.new("uint8_t[?]", n)
|
||||||
local buflen = ffi.new("unsigned long[1]", n) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">④</span>
|
local buflen = ffi.new("unsigned long[1]", n)
|
||||||
local res = zlib.compress2(buf, buflen, txt, #txt, 9)
|
local res = zlib.compress2(buf, buflen, txt, #txt, 9)
|
||||||
assert(res == 0)
|
assert(res == 0)
|
||||||
return ffi.string(buf, buflen[0]) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">⑤</span>
|
return ffi.string(buf, buflen[0])
|
||||||
end
|
end
|
||||||
|
|
||||||
local function uncompress(comp, n) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">⑥</span>
|
local function uncompress(comp, n)
|
||||||
local buf = ffi.new("uint8_t[?]", n)
|
local buf = ffi.new("uint8_t[?]", n)
|
||||||
local buflen = ffi.new("unsigned long[1]", n)
|
local buflen = ffi.new("unsigned long[1]", n)
|
||||||
local res = zlib.uncompress(buf, buflen, comp, #comp)
|
local res = zlib.uncompress(buf, buflen, comp, #comp)
|
||||||
@ -224,7 +275,7 @@ local function uncompress(comp, n) <span style="color:#f0f4ff;">--</span><span s
|
|||||||
return ffi.string(buf, buflen[0])
|
return ffi.string(buf, buflen[0])
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Simple test code. <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">⑦</span>
|
-- Simple test code.
|
||||||
local txt = string.rep("abcd", 1000)
|
local txt = string.rep("abcd", 1000)
|
||||||
print("Uncompressed size: ", #txt)
|
print("Uncompressed size: ", #txt)
|
||||||
local c = compress(txt)
|
local c = compress(txt)
|
||||||
@ -236,13 +287,13 @@ assert(txt2 == txt)
|
|||||||
Here's the step-by-step explanation:
|
Here's the step-by-step explanation:
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">①</span> This defines some of the
|
<span class="mark">①</span> This defines some of the
|
||||||
C functions provided by zlib. For the sake of this example, some
|
C functions provided by zlib. For the sake of this example, some
|
||||||
type indirections have been reduced and it uses the pre-defined
|
type indirections have been reduced and it uses the pre-defined
|
||||||
fixed-size integer types, while still adhering to the zlib API/ABI.
|
fixed-size integer types, while still adhering to the zlib API/ABI.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">②</span> This loads the zlib shared
|
<span class="mark">②</span> This loads the zlib shared
|
||||||
library. On POSIX systems it's named <tt>libz.so</tt> and usually
|
library. On POSIX systems it's named <tt>libz.so</tt> and usually
|
||||||
comes pre-installed. Since <tt>ffi.load()</tt> automatically adds any
|
comes pre-installed. Since <tt>ffi.load()</tt> automatically adds any
|
||||||
missing standard prefixes/suffixes, we can simply load the
|
missing standard prefixes/suffixes, we can simply load the
|
||||||
@ -253,7 +304,7 @@ you'll have to download it first from the
|
|||||||
<tt>ffi.load()</tt>.
|
<tt>ffi.load()</tt>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">③</span> First, the maximum size of
|
<span class="mark">③</span> First, the maximum size of
|
||||||
the compression buffer is obtained by calling the
|
the compression buffer is obtained by calling the
|
||||||
<tt>zlib.compressBound</tt> function with the length of the
|
<tt>zlib.compressBound</tt> function with the length of the
|
||||||
uncompressed string. The next line allocates a byte buffer of this
|
uncompressed string. The next line allocates a byte buffer of this
|
||||||
@ -262,7 +313,7 @@ variable-length array (VLA). The actual number of elements of this
|
|||||||
array is given as the 2nd argument to <tt>ffi.new()</tt>.
|
array is given as the 2nd argument to <tt>ffi.new()</tt>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">④</span> This may look strange at
|
<span class="mark">④</span> This may look strange at
|
||||||
first, but have a look at the declaration of the <tt>compress2</tt>
|
first, but have a look at the declaration of the <tt>compress2</tt>
|
||||||
function from zlib: the destination length is defined as a pointer!
|
function from zlib: the destination length is defined as a pointer!
|
||||||
This is because you pass in the maximum buffer size and get back the
|
This is because you pass in the maximum buffer size and get back the
|
||||||
@ -276,7 +327,7 @@ initialized with the maximum buffer size in one step. Calling the
|
|||||||
actual <tt>zlib.compress2</tt> function is then straightforward.
|
actual <tt>zlib.compress2</tt> function is then straightforward.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">⑤</span> We want to return the
|
<span class="mark">⑤</span> We want to return the
|
||||||
compressed data as a Lua string, so we'll use <tt>ffi.string()</tt>.
|
compressed data as a Lua string, so we'll use <tt>ffi.string()</tt>.
|
||||||
It needs a pointer to the start of the data and the actual length. The
|
It needs a pointer to the start of the data and the actual length. The
|
||||||
length has been returned in the <tt>buflen</tt> array, so we'll just
|
length has been returned in the <tt>buflen</tt> array, so we'll just
|
||||||
@ -292,13 +343,13 @@ results in buffers instead of strings. This will reduce the overhead
|
|||||||
for garbage collection and string interning.
|
for garbage collection and string interning.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">⑥</span> The <tt>uncompress</tt>
|
<span class="mark">⑥</span> The <tt>uncompress</tt>
|
||||||
functions does the exact opposite of the <tt>compress</tt> function.
|
functions does the exact opposite of the <tt>compress</tt> function.
|
||||||
The compressed data doesn't include the size of the original string,
|
The compressed data doesn't include the size of the original string,
|
||||||
so this needs to be passed in. Otherwise no surprises here.
|
so this needs to be passed in. Otherwise no surprises here.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span style="color:#4040c0;">⑦</span> The code, that makes use
|
<span class="mark">⑦</span> The code, that makes use
|
||||||
of the functions we just defined, is just plain Lua code. It doesn't
|
of the functions we just defined, is just plain Lua code. It doesn't
|
||||||
need to know anything about the LuaJIT FFI — the convenience
|
need to know anything about the LuaJIT FFI — the convenience
|
||||||
wrapper functions completely hide it.
|
wrapper functions completely hide it.
|
||||||
|
@ -417,7 +417,7 @@ simply use whatever <tt>make install</tt> creates. There's a reason
|
|||||||
for all of the files <em>and</em> directories it creates.
|
for all of the files <em>and</em> directories it creates.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The build system uses GNU make and autodetects most settings based on
|
The build system uses GNU make and auto-detects most settings based on
|
||||||
the host you're building it on. This should work fine for native builds,
|
the host you're building it on. This should work fine for native builds,
|
||||||
even when sandboxed. You may need to pass some of the following flags to
|
even when sandboxed. You may need to pass some of the following flags to
|
||||||
<em>both</em> the <tt>make</tt> and the <tt>make install</tt> command lines
|
<em>both</em> the <tt>make</tt> and the <tt>make install</tt> command lines
|
||||||
@ -431,7 +431,7 @@ the <tt>-rpath</tt> of the shared library.</li>
|
|||||||
to a shadow tree instead of the root tree of the build system.</li>
|
to a shadow tree instead of the root tree of the build system.</li>
|
||||||
<li>Have a look at the top-level <tt>Makefile</tt> and <tt>src/Makefile</tt>
|
<li>Have a look at the top-level <tt>Makefile</tt> and <tt>src/Makefile</tt>
|
||||||
for additional variables to tweak. The following variables <em>may</em> be
|
for additional variables to tweak. The following variables <em>may</em> be
|
||||||
overriden, but it's <em>not</em> recommended, except for special needs
|
overridden, but it's <em>not</em> recommended, except for special needs
|
||||||
like cross-builds:
|
like cross-builds:
|
||||||
<tt>BUILDMODE, CC, HOST_CC, STATIC_CC, DYNAMIC_CC, CFLAGS, HOST_CFLAGS,
|
<tt>BUILDMODE, CC, HOST_CC, STATIC_CC, DYNAMIC_CC, CFLAGS, HOST_CFLAGS,
|
||||||
TARGET_CFLAGS, LDFLAGS, HOST_LDFLAGS, TARGET_LDFLAGS, TARGET_SHLDFLAGS,
|
TARGET_CFLAGS, LDFLAGS, HOST_LDFLAGS, TARGET_LDFLAGS, TARGET_SHLDFLAGS,
|
||||||
|
@ -96,7 +96,7 @@ performance and an unmatched <b>low memory footprint</b>: less than
|
|||||||
<p>
|
<p>
|
||||||
LuaJIT has been in continuous development since 2005. It's widely
|
LuaJIT has been in continuous development since 2005. It's widely
|
||||||
considered to be <b>one of the fastest dynamic language
|
considered to be <b>one of the fastest dynamic language
|
||||||
implementations</b>. It has outperfomed other dynamic languages on many
|
implementations</b>. It has outperformed other dynamic languages on many
|
||||||
cross-language benchmarks since its first release — often by a
|
cross-language benchmarks since its first release — often by a
|
||||||
substantial margin. In 2009 other dynamic language VMs started to catch up
|
substantial margin. In 2009 other dynamic language VMs started to catch up
|
||||||
with the performance of LuaJIT 1.x. Well, I couldn't let that slide. ;-)
|
with the performance of LuaJIT 1.x. Well, I couldn't let that slide. ;-)
|
||||||
|
@ -182,9 +182,10 @@ handled correctly. The error may fall through an on-trace
|
|||||||
|
|
||||||
<h2>Roadmap</h2>
|
<h2>Roadmap</h2>
|
||||||
<p>
|
<p>
|
||||||
Rather than stating exact release dates (I'm well known for making
|
Please refer to the
|
||||||
spectacularly wrong guesses), this roadmap lists the general project
|
<a href="http://lua-users.org/lists/lua-l/2011-01/msg01238.html"><span class="ext">»</span> LuaJIT
|
||||||
plan, sorted by priority, as well as ideas for the future:
|
Roadmap 2011</a> for the latest release plan. Here's the general
|
||||||
|
project plan for LuaJIT 2.0:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
|
Loading…
Reference in New Issue
Block a user