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