summaryrefslogtreecommitdiff
path: root/doc/ext_ffi.html
diff options
context:
space:
mode:
authorMike Pall <mike>2011-01-20 22:14:17 +0100
committerMike Pall <mike>2011-01-20 22:14:17 +0100
commite985aeda84d8af63c4bfaa176c3312dfb2f7f230 (patch)
tree8a68df0aac6779db0972bb9dc07fbbe0c7629bc7 /doc/ext_ffi.html
parent8396c3cdbc26e08fdf9dea204efb641dd6ad1f91 (diff)
downloadluajit-e985aeda84d8af63c4bfaa176c3312dfb2f7f230.tar.gz
luajit-e985aeda84d8af63c4bfaa176c3312dfb2f7f230.tar.bz2
luajit-e985aeda84d8af63c4bfaa176c3312dfb2f7f230.zip
FFI: Add preliminary FFI documentation (still incomplete).
Diffstat (limited to 'doc/ext_ffi.html')
-rw-r--r--doc/ext_ffi.html280
1 files changed, 280 insertions, 0 deletions
diff --git a/doc/ext_ffi.html b/doc/ext_ffi.html
new file mode 100644
index 00000000..e8e2a62b
--- /dev/null
+++ b/doc/ext_ffi.html
@@ -0,0 +1,280 @@
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
2<html>
3<head>
4<title>FFI Library</title>
5<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
6<meta name="Author" content="Mike Pall">
7<meta name="Copyright" content="Copyright (C) 2005-2011, Mike Pall">
8<meta name="Language" content="en">
9<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
10<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
11</head>
12<body>
13<div id="site">
14<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
15</div>
16<div id="head">
17<h1>FFI Library</h1>
18</div>
19<div id="nav">
20<ul><li>
21<a href="luajit.html">LuaJIT</a>
22<ul><li>
23<a href="install.html">Installation</a>
24</li><li>
25<a href="running.html">Running</a>
26</li></ul>
27</li><li>
28<a href="extensions.html">Extensions</a>
29<ul><li>
30<a class="current" href="ext_ffi.html">FFI Library</a>
31<ul><li>
32<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
33</li><li>
34<a href="ext_ffi_api.html">ffi.* API</a>
35</li><li>
36<a href="ext_ffi_int64.html">64 bit Integers</a>
37</li><li>
38<a href="ext_ffi_semantics.html">FFI Semantics</a>
39</li></ul>
40</li><li>
41<a href="ext_jit.html">jit.* Library</a>
42</li><li>
43<a href="ext_c_api.html">Lua/C API</a>
44</li></ul>
45</li><li>
46<a href="status.html">Status</a>
47<ul><li>
48<a href="changes.html">Changes</a>
49</li></ul>
50</li><li>
51<a href="faq.html">FAQ</a>
52</li><li>
53<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
54</li><li>
55<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
56</li></ul>
57</div>
58<div id="main">
59<p>
60The FFI library allows calling external C&nbsp;functions and the use
61of C&nbsp;data structures from pure Lua code.
62</p>
63<p>
64The FFI library largely obviates the need to write tedious manual
65Lua/C bindings in C. It doesn't require learning a separate binding
66language &mdash; it parses plain C&nbsp;declarations, which can be
67cut-n-pasted from C&nbsp;header files or reference manuals. It's up to
68the task of binding large libraries without the need for dealing with
69fragile binding generators.
70</p>
71<p>
72The FFI library is tightly integrated into LuaJIT (it's not available
73as a separate module). The code generated by the JIT-compiler for
74accesses to C&nbsp;data structures from Lua code is on par with the
75code a C&nbsp;compiler would generate. Calls to C&nbsp;functions can
76be inlined in the JIT-compiled code, unlike calls to functions bound
77via the classic Lua/C API.
78</p>
79<p>
80This page gives a short introduction to the usage of the FFI library.
81Please use the FFI sub-topics in the navigation bar to learn more.
82</p>
83
84<h2 id="call">Motivating Example: Calling External C Functions</h2>
85<p>
86It's really easy to call an external C&nbsp;library function:
87</p>
88<pre class="code">
89<span style="color:#000080;">local ffi = require("ffi")</span>
90ffi.cdef[[
91<span style="color:#00a000;font-weight:bold;">int printf(const char *fmt, ...);</span>
92]]
93<span style="color:#c06000;font-weight:bold;">ffi.C</span>.printf("Hello %s!", "world")
94</pre>
95<p>
96So, let's pick that apart: the first line (in blue) loads the FFI
97library. The next one adds a C&nbsp;declaration for the function. The
98part between the double-brackets (in green) is just standard
99C&nbsp;syntax. And the last line calls the named C&nbsp;function. Yes,
100it's that simple!
101</p>
102<p style="font-size: 8pt;">
103Actually, what goes on behind the scenes is far from simple: the first
104part of the last line (in orange) makes use of the standard
105C&nbsp;library namespace <tt>ffi.C</tt>. Indexing this namespace with
106a symbol name (<tt>"printf"</tt>) automatically binds it to the the
107standard C&nbsp;library. The result is a special kind of object which,
108when called, runs the <tt>printf</tt> function. The arguments passed
109to this function are automatically converted from Lua objects to the
110corresponding C&nbsp;types.
111</p>
112<p>
113Ok, so maybe the use of <tt>printf()</tt> wasn't such a spectacular
114example. You could have done that with <tt>io.write()</tt> and
115<tt>string.format()</tt>, too. But you get the idea ...
116</p>
117<p>
118So here's something to pop up a message box on Windows:
119</p>
120<pre class="code">
121local ffi = require("ffi")
122ffi.cdef[[
123int MessageBoxA(void *w, const char *txt, const char *cap, int type);
124]]
125ffi.C.MessageBoxA(nil, "Hello world!", "Test", 0)
126</pre>
127<p>
128Bing! Again, that was far too easy, no?
129</p>
130<p style="font-size: 8pt;">
131Compare this with the effort required to bind that function using the
132classic Lua/C API: create an extra C&nbsp;file, add a C&nbsp;function
133that retrieves and checks the argument types passed from Lua and calls
134the actual C&nbsp;function, add a list of module functions and their
135names, add a <tt>luaopen_*</tt> function and register all module
136functions, compile and link it into a shared library (DLL), move it to
137the proper path, add Lua code that loads the module aaaand ... finally
138call the binding function. Phew!
139</p>
140
141<h2 id="call">Motivating Example: Using C Data Structures</h2>
142<p>
143The FFI library allows you to create and access C&nbsp;data
144structures. Of course the main use for this is for interfacing with
145C&nbsp;functions. But they can be used stand-alone, too.
146</p>
147<p>
148Lua is built upon high-level data types. They are flexible, extensible
149and dynamic. That's why we all love Lua so much. Alas, this can be
150inefficient for certain tasks, where you'd really want a low-level
151data type. E.g. a large array of a fixed structure needs to be
152implemented with a big table holding lots of tiny tables. This imposes
153both a substantial memory overhead as well as a performance overhead.
154</p>
155<p>
156Here's a sketch of a library that operates on color images plus a
157simple benchmark. First, the plain Lua version:
158</p>
159<pre class="code">
160local floor = math.floor
161
162local function image_ramp_green(n)
163 local img = {}
164 local f = 255/(n-1)
165 for i=1,n do
166 img[i] = { red = 0, green = floor((i-1)*f), blue = 0, alpha = 255 }
167 end
168 return img
169end
170
171local function image_to_grey(img, n)
172 for i=1,n do
173 local y = floor(0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue)
174 img[i].red = y; img[i].green = y; img[i].blue = y
175 end
176end
177
178local N = 400*400
179local img = image_ramp_green(N)
180for i=1,1000 do
181 image_to_grey(img, N)
182end
183</pre>
184<p>
185This creates a table with 160.000 pixels, each of which is a table
186holding four number values in the range of 0-255. First an image with
187a green ramp is created (1D for simplicity), then the image is
188converted to greyscale 1000 times. Yes, that's silly, but I was in
189need of a simple example ...
190</p>
191<p>
192And here's the FFI version. The modified parts have been marked in
193bold:
194</p>
195<pre class="code">
196<b>local ffi = require("ffi")
197ffi.cdef[[
198typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel;
199]]</b>
200
201local function image_ramp_green(n)
202 <b>local img = ffi.new("rgba_pixel[?]", n)</b>
203 local f = 255/(n-1)
204 for i=<b>0,n-1</b> do
205 <b>img[i].green = i*f</b>
206 <b>img[i].alpha = 255</b>
207 end
208 return img
209end
210
211local function image_to_grey(img, n)
212 for i=<b>0,n-1</b> do
213 local y = <b>0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue</b>
214 img[i].red = y; img[i].green = y; img[i].blue = y
215 end
216end
217
218local N = 400*400
219local img = image_ramp_green(N)
220for i=1,1000 do
221 image_to_grey(img, N)
222end
223</pre>
224<p>
225Ok, so that wasn't too difficult: first, load the FFI library and
226declare the low-level data type. Here we choose a <tt>struct</tt>
227which holds four byte fields, one for each component of a 4x8&nbsp;bit
228RGBA pixel.
229</p>
230<p>
231Creating the data structure with <tt>ffi.new()</tt> is straightforward
232&mdash; the <tt>'?'</tt> is a placeholder for the number of elements
233of a variable-length array. C&nbsp;arrays are zero-based, so the
234indexes have to run from <tt>0</tt> to <tt>n-1</tt> (one might
235allocate one more element instead to simplify converting legacy
236code). Since <tt>ffi.new()</tt> zero-fills the array by default, we
237only need to set the green and the alpha fields.
238</p>
239<p>
240The calls to <tt>math.floor()</tt> can be omitted here, because
241floating-point numbers are already truncated towards zero when
242converting them to an integer. This happens implicitly when the number
243is stored in the fields of each pixel.
244</p>
245<p>
246Now let's have a look at the impact of the changes: first, memory
247consumption for the image is down from 22&nbsp;Megabytes to
248640&nbsp;Kilobytes (400*400*4 bytes). That's a factor of 35x less! So,
249yes, tables do have a noticeable overhead. BTW: The original program
250would consume 40&nbsp;Megabytes in plain Lua (on x64).
251</p>
252<p>
253Next, performance: the pure Lua version runs in 9.57 seconds (52.9
254seconds with the Lua interpreter) and the FFI version runs in 0.48
255seconds on my machine (YMMV). That's a factor of 20x faster (110x
256faster than with plain Lua).
257</p>
258<p style="font-size: 8pt;">
259The avid reader may notice that converting the pure Lua version over
260to use array indexes for the colors (<tt>[1]</tt> instead of
261<tt>.red</tt>, <tt>[2]</tt> instead of <tt>.green</tt> etc.) ought to
262be more compact and faster. This is certainly true (by a factor of
263~1.7x), but the resulting code would be less idiomatic and rather
264error-prone. And it still doesn't get even close to the performance of
265the FFI version of the code. Also, high-level data structures cannot
266be easily passed to other C&nbsp;functions, especially I/O functions,
267without undue conversion penalties.
268</p>
269<br class="flush">
270</div>
271<div id="foot">
272<hr class="hide">
273Copyright &copy; 2005-2011 Mike Pall
274<span class="noprint">
275&middot;
276<a href="contact.html">Contact</a>
277</span>
278</div>
279</body>
280</html>