aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/luajit-2.0/doc/ext_ffi_tutorial.html
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/luajit-2.0/doc/ext_ffi_tutorial.html')
-rw-r--r--libraries/luajit-2.0/doc/ext_ffi_tutorial.html598
1 files changed, 0 insertions, 598 deletions
diff --git a/libraries/luajit-2.0/doc/ext_ffi_tutorial.html b/libraries/luajit-2.0/doc/ext_ffi_tutorial.html
deleted file mode 100644
index fb46a84..0000000
--- a/libraries/luajit-2.0/doc/ext_ffi_tutorial.html
+++ /dev/null
@@ -1,598 +0,0 @@
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 Tutorial</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<style type="text/css">
12span.codemark { position:absolute; left: 16em; color: #4040c0; }
13span.mark { color: #4040c0; font-family: Courier New, Courier, monospace;
14 line-height: 1.1; }
15pre.mark { padding-left: 2em; }
16table.idiomtable { line-height: 1.2; }
17table.idiomtable tt { font-size: 100%; }
18table.idiomtable td { vertical-align: top; }
19tr.idiomhead td { font-weight: bold; }
20td.idiomc { width: 12em; }
21td.idiomlua { width: 14em; }
22td.idiomlua b { font-weight: normal; color: #2142bf; }
23</style>
24</head>
25<body>
26<div id="site">
27<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
28</div>
29<div id="head">
30<h1>FFI Tutorial</h1>
31</div>
32<div id="nav">
33<ul><li>
34<a href="luajit.html">LuaJIT</a>
35<ul><li>
36<a href="install.html">Installation</a>
37</li><li>
38<a href="running.html">Running</a>
39</li></ul>
40</li><li>
41<a href="extensions.html">Extensions</a>
42<ul><li>
43<a href="ext_ffi.html">FFI Library</a>
44<ul><li>
45<a class="current" href="ext_ffi_tutorial.html">FFI Tutorial</a>
46</li><li>
47<a href="ext_ffi_api.html">ffi.* API</a>
48</li><li>
49<a href="ext_ffi_semantics.html">FFI Semantics</a>
50</li></ul>
51</li><li>
52<a href="ext_jit.html">jit.* Library</a>
53</li><li>
54<a href="ext_c_api.html">Lua/C API</a>
55</li></ul>
56</li><li>
57<a href="status.html">Status</a>
58<ul><li>
59<a href="changes.html">Changes</a>
60</li></ul>
61</li><li>
62<a href="faq.html">FAQ</a>
63</li><li>
64<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
65</li><li>
66<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
67</li></ul>
68</div>
69<div id="main">
70<p>
71This page is intended to give you an overview of the features of the FFI
72library by presenting a few use cases and guidelines.
73</p>
74<p>
75This page makes no attempt to explain all of the FFI library, though.
76You'll want to have a look at the <a href="ext_ffi_api.html">ffi.* API
77function reference</a> and the <a href="ext_ffi_semantics.html">FFI
78semantics</a> to learn more.
79</p>
80
81<h2 id="load">Loading the FFI Library</h2>
82<p>
83The FFI library is built into LuaJIT by default, but it's not loaded
84and initialized by default. The suggested way to use the FFI library
85is to add the following to the start of every Lua file that needs one
86of its functions:
87</p>
88<pre class="code">
89local ffi = require("ffi")
90</pre>
91<p>
92Please note this doesn't define an <tt>ffi</tt> variable in the table
93of globals &mdash; you really need to use the local variable. The
94<tt>require</tt> function ensures the library is only loaded once.
95</p>
96
97<h2 id="sleep">Accessing Standard System Functions</h2>
98<p>
99The following code explains how to access standard system functions.
100We slowly print two lines of dots by sleeping for 10&nbsp;milliseconds
101after each dot:
102</p>
103<pre class="code mark">
104<span class="codemark">&nbsp;
105&#9312;
106
107
108
109
110
111&#9313;
112&#9314;
113&#9315;
114
115
116
117&#9316;
118
119
120
121
122
123&#9317;</span>local ffi = require("ffi")
124ffi.cdef[[
125<span style="color:#00a000;">void Sleep(int ms);
126int poll(struct pollfd *fds, unsigned long nfds, int timeout);</span>
127]]
128
129local sleep
130if ffi.os == "Windows" then
131 function sleep(s)
132 ffi.C.Sleep(s*1000)
133 end
134else
135 function sleep(s)
136 ffi.C.poll(nil, 0, s*1000)
137 end
138end
139
140for i=1,160 do
141 io.write("."); io.flush()
142 sleep(0.01)
143end
144io.write("\n")
145</pre>
146<p>
147Here's the step-by-step explanation:
148</p>
149<p>
150<span class="mark">&#9312;</span> This defines the
151C&nbsp;library functions we're going to use. The part inside the
152double-brackets (in green) is just standard C&nbsp;syntax. You can
153usually get this info from the C&nbsp;header files or the
154documentation provided by each C&nbsp;library or C&nbsp;compiler.
155</p>
156<p>
157<span class="mark">&#9313;</span> The difficulty we're
158facing here, is that there are different standards to choose from.
159Windows has a simple <tt>Sleep()</tt> function. On other systems there
160are a variety of functions available to achieve sub-second sleeps, but
161with no clear consensus. Thankfully <tt>poll()</tt> can be used for
162this task, too, and it's present on most non-Windows systems. The
163check for <tt>ffi.os</tt> makes sure we use the Windows-specific
164function only on Windows systems.
165</p>
166<p>
167<span class="mark">&#9314;</span> Here we're wrapping the
168call to the C&nbsp;function in a Lua function. This isn't strictly
169necessary, but it's helpful to deal with system-specific issues only
170in one part of the code. The way we're wrapping it ensures the check
171for the OS is only done during initialization and not for every call.
172</p>
173<p>
174<span class="mark">&#9315;</span> A more subtle point is
175that we defined our <tt>sleep()</tt> function (for the sake of this
176example) as taking the number of seconds, but accepting fractional
177seconds. Multiplying this by 1000 gets us milliseconds, but that still
178leaves it a Lua number, which is a floating-point value. Alas, the
179<tt>Sleep()</tt> function only accepts an integer value. Luckily for
180us, the FFI library automatically performs the conversion when calling
181the function (truncating the FP value towards zero, like in C).
182</p>
183<p style="font-size: 8pt;">
184Some readers will notice that <tt>Sleep()</tt> is part of
185<tt>KERNEL32.DLL</tt> and is also a <tt>stdcall</tt> function. So how
186can this possibly work? The FFI library provides the <tt>ffi.C</tt>
187default C&nbsp;library namespace, which allows calling functions from
188the default set of libraries, like a C&nbsp;compiler would. Also, the
189FFI library automatically detects <tt>stdcall</tt> functions, so you
190don't need to declare them as such.
191</p>
192<p>
193<span class="mark">&#9316;</span> The <tt>poll()</tt>
194function takes a couple more arguments we're not going to use. You can
195simply use <tt>nil</tt> to pass a <tt>NULL</tt> pointer and <tt>0</tt>
196for the <tt>nfds</tt> parameter. Please note that the
197number&nbsp;<tt>0</tt> <em>does not convert to a pointer value</em>,
198unlike in C++. You really have to pass pointers to pointer arguments
199and numbers to number arguments.
200</p>
201<p style="font-size: 8pt;">
202The page on <a href="ext_ffi_semantics.html">FFI semantics</a> has all
203of the gory details about
204<a href="ext_ffi_semantics.html#convert">conversions between Lua
205objects and C&nbsp;types</a>. For the most part you don't have to deal
206with this, as it's performed automatically and it's carefully designed
207to bridge the semantic differences between Lua and C.
208</p>
209<p>
210<span class="mark">&#9317;</span> Now that we have defined
211our own <tt>sleep()</tt> function, we can just call it from plain Lua
212code. That wasn't so bad, huh? Turning these boring animated dots into
213a fascinating best-selling game is left as an exercise for the reader.
214:-)
215</p>
216
217<h2 id="zlib">Accessing the zlib Compression Library</h2>
218<p>
219The following code shows how to access the <a
220href="http://zlib.net/">zlib</a> compression library from Lua code.
221We'll define two convenience wrapper functions that take a string and
222compress or uncompress it to another string:
223</p>
224<pre class="code mark">
225<span class="codemark">&nbsp;
226&#9312;
227
228
229
230
231
232
233&#9313;
234
235
236&#9314;
237
238&#9315;
239
240
241&#9316;
242
243
244&#9317;
245
246
247
248
249
250
251
252&#9318;</span>local ffi = require("ffi")
253ffi.cdef[[
254<span style="color:#00a000;">unsigned long compressBound(unsigned long sourceLen);
255int compress2(uint8_t *dest, unsigned long *destLen,
256 const uint8_t *source, unsigned long sourceLen, int level);
257int uncompress(uint8_t *dest, unsigned long *destLen,
258 const uint8_t *source, unsigned long sourceLen);</span>
259]]
260local zlib = ffi.load(ffi.os == "Windows" and "zlib1" or "z")
261
262local function compress(txt)
263 local n = zlib.compressBound(#txt)
264 local buf = ffi.new("uint8_t[?]", n)
265 local buflen = ffi.new("unsigned long[1]", n)
266 local res = zlib.compress2(buf, buflen, txt, #txt, 9)
267 assert(res == 0)
268 return ffi.string(buf, buflen[0])
269end
270
271local function uncompress(comp, n)
272 local buf = ffi.new("uint8_t[?]", n)
273 local buflen = ffi.new("unsigned long[1]", n)
274 local res = zlib.uncompress(buf, buflen, comp, #comp)
275 assert(res == 0)
276 return ffi.string(buf, buflen[0])
277end
278
279-- Simple test code.
280local txt = string.rep("abcd", 1000)
281print("Uncompressed size: ", #txt)
282local c = compress(txt)
283print("Compressed size: ", #c)
284local txt2 = uncompress(c, #txt)
285assert(txt2 == txt)
286</pre>
287<p>
288Here's the step-by-step explanation:
289</p>
290<p>
291<span class="mark">&#9312;</span> This defines some of the
292C&nbsp;functions provided by zlib. For the sake of this example, some
293type indirections have been reduced and it uses the pre-defined
294fixed-size integer types, while still adhering to the zlib API/ABI.
295</p>
296<p>
297<span class="mark">&#9313;</span> This loads the zlib shared
298library. On POSIX systems it's named <tt>libz.so</tt> and usually
299comes pre-installed. Since <tt>ffi.load()</tt> automatically adds any
300missing standard prefixes/suffixes, we can simply load the
301<tt>"z"</tt> library. On Windows it's named <tt>zlib1.dll</tt> and
302you'll have to download it first from the
303<a href="http://zlib.net/"><span class="ext">&raquo;</span>&nbsp;zlib site</a>. The check for
304<tt>ffi.os</tt> makes sure we pass the right name to
305<tt>ffi.load()</tt>.
306</p>
307<p>
308<span class="mark">&#9314;</span> First, the maximum size of
309the compression buffer is obtained by calling the
310<tt>zlib.compressBound</tt> function with the length of the
311uncompressed string. The next line allocates a byte buffer of this
312size. The <tt>[?]</tt> in the type specification indicates a
313variable-length array (VLA). The actual number of elements of this
314array is given as the 2nd argument to <tt>ffi.new()</tt>.
315</p>
316<p>
317<span class="mark">&#9315;</span> This may look strange at
318first, but have a look at the declaration of the <tt>compress2</tt>
319function from zlib: the destination length is defined as a pointer!
320This is because you pass in the maximum buffer size and get back the
321actual length that was used.
322</p>
323<p>
324In C you'd pass in the address of a local variable
325(<tt>&amp;buflen</tt>). But since there's no address-of operator in
326Lua, we'll just pass in a one-element array. Conveniently it can be
327initialized with the maximum buffer size in one step. Calling the
328actual <tt>zlib.compress2</tt> function is then straightforward.
329</p>
330<p>
331<span class="mark">&#9316;</span> We want to return the
332compressed data as a Lua string, so we'll use <tt>ffi.string()</tt>.
333It needs a pointer to the start of the data and the actual length. The
334length has been returned in the <tt>buflen</tt> array, so we'll just
335get it from there.
336</p>
337<p style="font-size: 8pt;">
338Note that since the function returns now, the <tt>buf</tt> and
339<tt>buflen</tt> variables will eventually be garbage collected. This
340is fine, because <tt>ffi.string()</tt> has copied the contents to a
341newly created (interned) Lua string. If you plan to call this function
342lots of times, consider reusing the buffers and/or handing back the
343results in buffers instead of strings. This will reduce the overhead
344for garbage collection and string interning.
345</p>
346<p>
347<span class="mark">&#9317;</span> The <tt>uncompress</tt>
348functions does the exact opposite of the <tt>compress</tt> function.
349The compressed data doesn't include the size of the original string,
350so this needs to be passed in. Otherwise no surprises here.
351</p>
352<p>
353<span class="mark">&#9318;</span> The code, that makes use
354of the functions we just defined, is just plain Lua code. It doesn't
355need to know anything about the LuaJIT FFI &mdash; the convenience
356wrapper functions completely hide it.
357</p>
358<p>
359One major advantage of the LuaJIT FFI is that you are now able to
360write those wrappers <em>in Lua</em>. And at a fraction of the time it
361would cost you to create an extra C&nbsp;module using the Lua/C API.
362Many of the simpler C&nbsp;functions can probably be used directly
363from your Lua code, without any wrappers.
364</p>
365<p style="font-size: 8pt;">
366Side note: the zlib API uses the <tt>long</tt> type for passing
367lengths and sizes around. But all those zlib functions actually only
368deal with 32&nbsp;bit values. This is an unfortunate choice for a
369public API, but may be explained by zlib's history &mdash; we'll just
370have to deal with it.
371</p>
372<p style="font-size: 8pt;">
373First, you should know that a <tt>long</tt> is a 64&nbsp;bit type e.g.
374on POSIX/x64 systems, but a 32&nbsp;bit type on Windows/x64 and on
37532&nbsp;bit systems. Thus a <tt>long</tt> result can be either a plain
376Lua number or a boxed 64&nbsp;bit integer cdata object, depending on
377the target system.
378</p>
379<p style="font-size: 8pt;">
380Ok, so the <tt>ffi.*</tt> functions generally accept cdata objects
381wherever you'd want to use a number. That's why we get a away with
382passing <tt>n</tt> to <tt>ffi.string()</tt> above. But other Lua
383library functions or modules don't know how to deal with this. So for
384maximum portability one needs to use <tt>tonumber()</tt> on returned
385<tt>long</tt> results before passing them on. Otherwise the
386application might work on some systems, but would fail in a POSIX/x64
387environment.
388</p>
389
390<h2 id="metatype">Defining Metamethods for a C&nbsp;Type</h2>
391<p>
392The following code explains how to define metamethods for a C type.
393We define a simple point type and add some operations to it:
394</p>
395<pre class="code mark">
396<span class="codemark">&nbsp;
397&#9312;
398
399
400
401&#9313;
402
403&#9314;
404
405&#9315;
406
407
408
409&#9316;
410
411&#9317;</span>local ffi = require("ffi")
412ffi.cdef[[
413<span style="color:#00a000;">typedef struct { double x, y; } point_t;</span>
414]]
415
416local point
417local mt = {
418 __add = function(a, b) return point(a.x+b.x, a.y+b.y) end,
419 __len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end,
420 __index = {
421 area = function(a) return a.x*a.x + a.y*a.y end,
422 },
423}
424point = ffi.metatype("point_t", mt)
425
426local a = point(3, 4)
427print(a.x, a.y) --> 3 4
428print(#a) --> 5
429print(a:area()) --> 25
430local b = a + point(0.5, 8)
431print(#b) --> 12.5
432</pre>
433<p>
434Here's the step-by-step explanation:
435</p>
436<p>
437<span class="mark">&#9312;</span> This defines the C&nbsp;type for a
438two-dimensional point object.
439</p>
440<p>
441<span class="mark">&#9313;</span> We have to declare the variable
442holding the point constructor first, because it's used inside of a
443metamethod.
444</p>
445<p>
446<span class="mark">&#9314;</span> Let's define an <tt>__add</tt>
447metamethod which adds the coordinates of two points and creates a new
448point object. For simplicity, this function assumes that both arguments
449are points. But it could be any mix of objects, if at least one operand
450is of the required type (e.g. adding a point plus a number or vice
451versa). Our <tt>__len</tt> metamethod returns the distance of a point to
452the origin.
453</p>
454<p>
455<span class="mark">&#9315;</span> If we run out of operators, we can
456define named methods, too. Here the <tt>__index</tt> table defines an
457<tt>area</tt> function. For custom indexing needs, one might want to
458define <tt>__index</tt> and <tt>__newindex</tt> <em>functions</em> instead.
459</p>
460<p>
461<span class="mark">&#9316;</span> This associates the metamethods with
462our C&nbsp;type. This only needs to be done once. For convenience, a
463constructor is returned by
464<a href="ext_ffi_api.html#ffi_metatype"><tt>ffi.metatype()</tt></a>.
465We're not required to use it, though. The original C&nbsp;type can still
466be used e.g. to create an array of points. The metamethods automatically
467apply to any and all uses of this type.
468</p>
469<p>
470Please note that the association with a metatable is permanent and
471<b>the metatable must not be modified afterwards!</b> Ditto for the
472<tt>__index</tt> table.
473</p>
474<p>
475<span class="mark">&#9317;</span> Here are some simple usage examples
476for the point type and their expected results. The pre-defined
477operations (such as <tt>a.x</tt>) can be freely mixed with the newly
478defined metamethods. Note that <tt>area</tt> is a method and must be
479called with the Lua syntax for methods: <tt>a:area()</tt>, not
480<tt>a.area()</tt>.
481</p>
482<p>
483The C&nbsp;type metamethod mechanism is most useful when used in
484conjunction with C&nbsp;libraries that are written in an object-oriented
485style. Creators return a pointer to a new instance and methods take an
486instance pointer as the first argument. Sometimes you can just point
487<tt>__index</tt> to the library namespace and <tt>__gc</tt> to the
488destructor and you're done. But often enough you'll want to add
489convenience wrappers, e.g. to return actual Lua strings or when
490returning multiple values.
491</p>
492<p>
493Some C libraries only declare instance pointers as an opaque
494<tt>void&nbsp;*</tt> type. In this case you can use a fake type for all
495declarations, e.g. a pointer to a named (incomplete) struct will do:
496<tt>typedef struct foo_type *foo_handle</tt>. The C&nbsp;side doesn't
497know what you declare with the LuaJIT FFI, but as long as the underlying
498types are compatible, everything still works.
499</p>
500
501<h2 id="idioms">Translating C&nbsp;Idioms</h2>
502<p>
503Here's a list of common C&nbsp;idioms and their translation to the
504LuaJIT FFI:
505</p>
506<table class="idiomtable">
507<tr class="idiomhead">
508<td class="idiomdesc">Idiom</td>
509<td class="idiomc">C&nbsp;code</td>
510<td class="idiomlua">Lua code</td>
511</tr>
512<tr class="odd separate">
513<td class="idiomdesc">Pointer dereference<br><tt>int *p;</tt></td><td class="idiomc"><tt>x = *p;<br>*p = y;</tt></td><td class="idiomlua"><tt>x = <b>p[0]</b><br><b>p[0]</b> = y</tt></td></tr>
514<tr class="even">
515<td class="idiomdesc">Pointer indexing<br><tt>int i, *p;</tt></td><td class="idiomc"><tt>x = p[i];<br>p[i+1] = y;</tt></td><td class="idiomlua"><tt>x = p[i]<br>p[i+1] = y</tt></td></tr>
516<tr class="odd">
517<td class="idiomdesc">Array indexing<br><tt>int i, a[];</tt></td><td class="idiomc"><tt>x = a[i];<br>a[i+1] = y;</tt></td><td class="idiomlua"><tt>x = a[i]<br>a[i+1] = y</tt></td></tr>
518<tr class="even separate">
519<td class="idiomdesc"><tt>struct</tt>/<tt>union</tt> dereference<br><tt>struct foo s;</tt></td><td class="idiomc"><tt>x = s.field;<br>s.field = y;</tt></td><td class="idiomlua"><tt>x = s.field<br>s.field = y</tt></td></tr>
520<tr class="odd">
521<td class="idiomdesc"><tt>struct</tt>/<tt>union</tt> pointer deref.<br><tt>struct foo *sp;</tt></td><td class="idiomc"><tt>x = sp->field;<br>sp->field = y;</tt></td><td class="idiomlua"><tt>x = <b>s.field</b><br><b>s.field</b> = y</tt></td></tr>
522<tr class="even separate">
523<td class="idiomdesc">Pointer arithmetic<br><tt>int i, *p;</tt></td><td class="idiomc"><tt>x = p + i;<br>y = p - i;</tt></td><td class="idiomlua"><tt>x = p + i<br>y = p - i</tt></td></tr>
524<tr class="odd">
525<td class="idiomdesc">Pointer difference<br><tt>int *p1, *p2;</tt></td><td class="idiomc"><tt>x = p1 - p2;</tt></td><td class="idiomlua"><tt>x = p1 - p2</tt></td></tr>
526<tr class="even">
527<td class="idiomdesc">Array element pointer<br><tt>int i, a[];</tt></td><td class="idiomc"><tt>x = &amp;a[i];</tt></td><td class="idiomlua"><tt>x = <b>a+i</b></tt></td></tr>
528<tr class="odd">
529<td class="idiomdesc">Cast pointer to address<br><tt>int *p;</tt></td><td class="idiomc"><tt>x = (intptr_t)p;</tt></td><td class="idiomlua"><tt>x = <b>tonumber(<br>&nbsp;ffi.cast("intptr_t",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p))</b></tt></td></tr>
530<tr class="even separate">
531<td class="idiomdesc">Functions with outargs<br><tt>void foo(int *inoutlen);</tt></td><td class="idiomc"><tt>int len = x;<br>foo(&amp;len);<br>y = len;</tt></td><td class="idiomlua"><tt><b>local len =<br>&nbsp;&nbsp;ffi.new("int[1]", x)<br>foo(len)<br>y = len[0]</b></tt></td></tr>
532<tr class="odd">
533<td class="idiomdesc"><a href="ext_ffi_semantics.html#convert_vararg">Vararg conversions</a><br><tt>int printf(char *fmt, ...);</tt></td><td class="idiomc"><tt>printf("%g", 1.0);<br>printf("%d", 1);<br>&nbsp;</tt></td><td class="idiomlua"><tt>printf("%g", 1);<br>printf("%d",<br>&nbsp;&nbsp;<b>ffi.new("int", 1)</b>)</tt></td></tr>
534</table>
535
536<h2 id="cache">To Cache or Not to Cache</h2>
537<p>
538It's a common Lua idiom to cache library functions in local variables
539or upvalues, e.g.:
540</p>
541<pre class="code">
542local byte, char = string.byte, string.char
543local function foo(x)
544 return char(byte(x)+1)
545end
546</pre>
547<p>
548This replaces several hash-table lookups with a (faster) direct use of
549a local or an upvalue. This is less important with LuaJIT, since the
550JIT compiler optimizes hash-table lookups a lot and is even able to
551hoist most of them out of the inner loops. It can't eliminate
552<em>all</em> of them, though, and it saves some typing for often-used
553functions. So there's still a place for this, even with LuaJIT.
554</p>
555<p>
556The situation is a bit different with C&nbsp;function calls via the
557FFI library. The JIT compiler has special logic to eliminate <em>all
558of the lookup overhead</em> for functions resolved from a
559<a href="ext_ffi_semantics.html#clib">C&nbsp;library namespace</a>!
560Thus it's not helpful and actually counter-productive to cache
561individual C&nbsp;functions like this:
562</p>
563<pre class="code">
564local <b>funca</b>, <b>funcb</b> = ffi.C.funcb, ffi.C.funcb -- <span style="color:#c00000;">Not helpful!</span>
565local function foo(x, n)
566 for i=1,n do <b>funcb</b>(<b>funca</b>(x, i), 1) end
567end
568</pre>
569<p>
570This turns them into indirect calls and generates bigger and slower
571machine code. Instead you'll want to cache the namespace itself and
572rely on the JIT compiler to eliminate the lookups:
573</p>
574<pre class="code">
575local <b>C</b> = ffi.C -- <span style="color:#00a000;">Instead use this!</span>
576local function foo(x, n)
577 for i=1,n do <b>C.funcb</b>(<b>C.funca</b>(x, i), 1) end
578end
579</pre>
580<p>
581This generates both shorter and faster code. So <b>don't cache
582C&nbsp;functions</b>, but <b>do</b> cache namespaces! Most often the
583namespace is already in a local variable at an outer scope, e.g. from
584<tt>local&nbsp;lib&nbsp;=&nbsp;ffi.load(...)</tt>. Note that copying
585it to a local variable in the function scope is unnecessary.
586</p>
587<br class="flush">
588</div>
589<div id="foot">
590<hr class="hide">
591Copyright &copy; 2005-2011 Mike Pall
592<span class="noprint">
593&middot;
594<a href="contact.html">Contact</a>
595</span>
596</div>
597</body>
598</html>