diff options
author | Mike Pall <mike> | 2011-02-11 01:21:46 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2011-02-11 01:21:46 +0100 |
commit | a5aade2fa9ff89f9f3c4a91261071299de0d0fa4 (patch) | |
tree | d253cfe022944c9754ebe43810a73c141130f058 /doc | |
parent | a2f9f1f831c77b19433b9f8858b9c1db0e421800 (diff) | |
download | luajit-a5aade2fa9ff89f9f3c4a91261071299de0d0fa4.tar.gz luajit-a5aade2fa9ff89f9f3c4a91261071299de0d0fa4.tar.bz2 luajit-a5aade2fa9ff89f9f3c4a91261071299de0d0fa4.zip |
FFI: Finish FFI docs.
Diffstat (limited to 'doc')
-rw-r--r-- | doc/changes.html | 2 | ||||
-rw-r--r-- | doc/contact.html | 2 | ||||
-rw-r--r-- | doc/ext_c_api.html | 2 | ||||
-rw-r--r-- | doc/ext_ffi.html | 92 | ||||
-rw-r--r-- | doc/ext_ffi_api.html | 49 | ||||
-rw-r--r-- | doc/ext_ffi_int64.html | 73 | ||||
-rw-r--r-- | doc/ext_ffi_semantics.html | 40 | ||||
-rw-r--r-- | doc/ext_ffi_tutorial.html | 352 | ||||
-rw-r--r-- | doc/ext_jit.html | 2 | ||||
-rw-r--r-- | doc/extensions.html | 2 | ||||
-rw-r--r-- | doc/faq.html | 2 | ||||
-rw-r--r-- | doc/install.html | 2 | ||||
-rw-r--r-- | doc/luajit.html | 2 | ||||
-rw-r--r-- | doc/running.html | 2 | ||||
-rw-r--r-- | doc/status.html | 2 |
15 files changed, 469 insertions, 157 deletions
diff --git a/doc/changes.html b/doc/changes.html index 2107193a..04e26e40 100644 --- a/doc/changes.html +++ b/doc/changes.html | |||
@@ -36,8 +36,6 @@ div.major { max-width: 600px; padding: 1em; margin: 1em 0 1em 0; } | |||
36 | </li><li> | 36 | </li><li> |
37 | <a href="ext_ffi_api.html">ffi.* API</a> | 37 | <a href="ext_ffi_api.html">ffi.* API</a> |
38 | </li><li> | 38 | </li><li> |
39 | <a href="ext_ffi_int64.html">64 bit Integers</a> | ||
40 | </li><li> | ||
41 | <a href="ext_ffi_semantics.html">FFI Semantics</a> | 39 | <a href="ext_ffi_semantics.html">FFI Semantics</a> |
42 | </li></ul> | 40 | </li></ul> |
43 | </li><li> | 41 | </li><li> |
diff --git a/doc/contact.html b/doc/contact.html index a979cb2f..a85c4884 100644 --- a/doc/contact.html +++ b/doc/contact.html | |||
@@ -33,8 +33,6 @@ | |||
33 | </li><li> | 33 | </li><li> |
34 | <a href="ext_ffi_api.html">ffi.* API</a> | 34 | <a href="ext_ffi_api.html">ffi.* API</a> |
35 | </li><li> | 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> | 36 | <a href="ext_ffi_semantics.html">FFI Semantics</a> |
39 | </li></ul> | 37 | </li></ul> |
40 | </li><li> | 38 | </li><li> |
diff --git a/doc/ext_c_api.html b/doc/ext_c_api.html index 119c89f5..35e2234e 100644 --- a/doc/ext_c_api.html +++ b/doc/ext_c_api.html | |||
@@ -33,8 +33,6 @@ | |||
33 | </li><li> | 33 | </li><li> |
34 | <a href="ext_ffi_api.html">ffi.* API</a> | 34 | <a href="ext_ffi_api.html">ffi.* API</a> |
35 | </li><li> | 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> | 36 | <a href="ext_ffi_semantics.html">FFI Semantics</a> |
39 | </li></ul> | 37 | </li></ul> |
40 | </li><li> | 38 | </li><li> |
diff --git a/doc/ext_ffi.html b/doc/ext_ffi.html index 50a44052..1fd276dc 100644 --- a/doc/ext_ffi.html +++ b/doc/ext_ffi.html | |||
@@ -33,8 +33,6 @@ | |||
33 | </li><li> | 33 | </li><li> |
34 | <a href="ext_ffi_api.html">ffi.* API</a> | 34 | <a href="ext_ffi_api.html">ffi.* API</a> |
35 | </li><li> | 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> | 36 | <a href="ext_ffi_semantics.html">FFI Semantics</a> |
39 | </li></ul> | 37 | </li></ul> |
40 | </li><li> | 38 | </li><li> |
@@ -86,22 +84,30 @@ Please use the FFI sub-topics in the navigation bar to learn more. | |||
86 | It's really easy to call an external C library function: | 84 | It's really easy to call an external C library function: |
87 | </p> | 85 | </p> |
88 | <pre class="code"> | 86 | <pre class="code"> |
89 | <span style="color:#000080;">local ffi = require("ffi")</span> | 87 | local ffi = require("ffi") <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">①</span> |
90 | ffi.cdef[[ | 88 | ffi.cdef[[ <span style="color:#f0f4ff;">//</span><span style="color:#4040c0;">②</span> |
91 | <span style="color:#00a000;font-weight:bold;">int printf(const char *fmt, ...);</span> | 89 | <span style="color:#00a000;">int printf(const char *fmt, ...);</span> |
92 | ]] | 90 | ]] |
93 | <span style="color:#c06000;font-weight:bold;">ffi.C</span>.printf("Hello %s!", "world") | 91 | ffi.C.printf("Hello %s!", "world") <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">③</span> |
94 | </pre> | 92 | </pre> |
95 | <p> | 93 | <p> |
96 | So, let's pick that apart: the first line (in blue) loads the FFI | 94 | So, let's pick that apart: |
97 | library. The next one adds a C declaration for the function. The | 95 | </p> |
98 | part between the double-brackets (in green) is just standard | 96 | <p> |
99 | C syntax. And the last line calls the named C function. Yes, | 97 | <span style="color:#4040c0;">①</span> Load the FFI library. |
100 | it's that simple! | 98 | </p> |
99 | <p> | ||
100 | <span style="color:#4040c0;">②</span> Add a C declaration | ||
101 | for the function. The part inside the double-brackets (in green) is | ||
102 | just standard C syntax. | ||
103 | </p> | ||
104 | <p> | ||
105 | <span style="color:#4040c0;">③</span> Call the named | ||
106 | C function — Yes, it's that simple! | ||
101 | </p> | 107 | </p> |
102 | <p style="font-size: 8pt;"> | 108 | <p style="font-size: 8pt;"> |
103 | Actually, what goes on behind the scenes is far from simple: the first | 109 | Actually, what goes on behind the scenes is far from simple: <span |
104 | part of the last line (in orange) makes use of the standard | 110 | style="color:#4040c0;">③</span> makes use of the standard |
105 | C library namespace <tt>ffi.C</tt>. Indexing this namespace with | 111 | C library namespace <tt>ffi.C</tt>. Indexing this namespace with |
106 | a symbol name (<tt>"printf"</tt>) automatically binds it to the the | 112 | a symbol name (<tt>"printf"</tt>) automatically binds it to the the |
107 | standard C library. The result is a special kind of object which, | 113 | standard C library. The result is a special kind of object which, |
@@ -120,7 +126,7 @@ So here's something to pop up a message box on Windows: | |||
120 | <pre class="code"> | 126 | <pre class="code"> |
121 | local ffi = require("ffi") | 127 | local ffi = require("ffi") |
122 | ffi.cdef[[ | 128 | ffi.cdef[[ |
123 | int MessageBoxA(void *w, const char *txt, const char *cap, int type); | 129 | <span style="color:#00a000;">int MessageBoxA(void *w, const char *txt, const char *cap, int type);</span> |
124 | ]] | 130 | ]] |
125 | ffi.C.MessageBoxA(nil, "Hello world!", "Test", 0) | 131 | ffi.C.MessageBoxA(nil, "Hello world!", "Test", 0) |
126 | </pre> | 132 | </pre> |
@@ -193,24 +199,24 @@ And here's the FFI version. The modified parts have been marked in | |||
193 | bold: | 199 | bold: |
194 | </p> | 200 | </p> |
195 | <pre class="code"> | 201 | <pre class="code"> |
196 | <b>local ffi = require("ffi") | 202 | <b>local ffi = require("ffi")</b> <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">①</span> |
197 | ffi.cdef[[ | 203 | <b>ffi.cdef[[ |
198 | typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel; | 204 | </b><span style="color:#00a000;">typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel;</span><b> |
199 | ]]</b> | 205 | ]]</b> |
200 | 206 | ||
201 | local function image_ramp_green(n) | 207 | local function image_ramp_green(n) |
202 | <b>local img = ffi.new("rgba_pixel[?]", n)</b> | 208 | <b>local img = ffi.new("rgba_pixel[?]", n)</b> <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">②</span> |
203 | local f = 255/(n-1) | 209 | local f = 255/(n-1) |
204 | for i=<b>0,n-1</b> do | 210 | for i=<b>0,n-1</b> do <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">③</span> |
205 | <b>img[i].green = i*f</b> | 211 | <b>img[i].green = i*f</b> <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">④</span> |
206 | <b>img[i].alpha = 255</b> | 212 | <b>img[i].alpha = 255</b> |
207 | end | 213 | end |
208 | return img | 214 | return img |
209 | end | 215 | end |
210 | 216 | ||
211 | local function image_to_grey(img, n) | 217 | local function image_to_grey(img, n) |
212 | for i=<b>0,n-1</b> do | 218 | for i=<b>0,n-1</b> do <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">③</span> |
213 | local y = <b>0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue</b> | 219 | 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> |
214 | img[i].red = y; img[i].green = y; img[i].blue = y | 220 | img[i].red = y; img[i].green = y; img[i].blue = y |
215 | end | 221 | end |
216 | end | 222 | end |
@@ -222,25 +228,37 @@ for i=1,1000 do | |||
222 | end | 228 | end |
223 | </pre> | 229 | </pre> |
224 | <p> | 230 | <p> |
225 | Ok, so that wasn't too difficult: first, load the FFI library and | 231 | Ok, so that wasn't too difficult: |
226 | declare the low-level data type. Here we choose a <tt>struct</tt> | 232 | </p> |
227 | which holds four byte fields, one for each component of a 4x8 bit | 233 | <p> |
228 | RGBA pixel. | 234 | <span style="color:#4040c0;">①</span> First, load the FFI |
235 | library and declare the low-level data type. Here we choose a | ||
236 | <tt>struct</tt> which holds four byte fields, one for each component | ||
237 | of a 4x8 bit RGBA pixel. | ||
238 | </p> | ||
239 | <p> | ||
240 | <span style="color:#4040c0;">②</span> Creating the data | ||
241 | structure with <tt>ffi.new()</tt> is straightforward — the | ||
242 | <tt>'?'</tt> is a placeholder for the number of elements of a | ||
243 | variable-length array. | ||
244 | </p> | ||
245 | <p> | ||
246 | <span style="color:#4040c0;">③</span> C arrays are | ||
247 | zero-based, so the indexes have to run from <tt>0</tt> to | ||
248 | <tt>n-1</tt>. One might want to allocate one more element instead to | ||
249 | simplify converting legacy code. | ||
229 | </p> | 250 | </p> |
230 | <p> | 251 | <p> |
231 | Creating the data structure with <tt>ffi.new()</tt> is straightforward | 252 | <span style="color:#4040c0;">④</span> Since <tt>ffi.new()</tt> |
232 | — the <tt>'?'</tt> is a placeholder for the number of elements | 253 | zero-fills the array by default, we only need to set the green and the |
233 | of a variable-length array. C arrays are zero-based, so the | 254 | alpha fields. |
234 | indexes have to run from <tt>0</tt> to <tt>n-1</tt> (one might | ||
235 | allocate one more element instead to simplify converting legacy | ||
236 | code). Since <tt>ffi.new()</tt> zero-fills the array by default, we | ||
237 | only need to set the green and the alpha fields. | ||
238 | </p> | 255 | </p> |
239 | <p> | 256 | <p> |
240 | The calls to <tt>math.floor()</tt> can be omitted here, because | 257 | <span style="color:#4040c0;">⑤</span> The calls to |
241 | floating-point numbers are already truncated towards zero when | 258 | <tt>math.floor()</tt> can be omitted here, because floating-point |
242 | converting them to an integer. This happens implicitly when the number | 259 | numbers are already truncated towards zero when converting them to an |
243 | is stored in the fields of each pixel. | 260 | integer. This happens implicitly when the number is stored in the |
261 | fields of each pixel. | ||
244 | </p> | 262 | </p> |
245 | <p> | 263 | <p> |
246 | Now let's have a look at the impact of the changes: first, memory | 264 | Now let's have a look at the impact of the changes: first, memory |
diff --git a/doc/ext_ffi_api.html b/doc/ext_ffi_api.html index 7c2e53dd..9bedd52e 100644 --- a/doc/ext_ffi_api.html +++ b/doc/ext_ffi_api.html | |||
@@ -38,8 +38,6 @@ td.abiparam { font-weight: bold; width: 6em; } | |||
38 | </li><li> | 38 | </li><li> |
39 | <a class="current" href="ext_ffi_api.html">ffi.* API</a> | 39 | <a class="current" href="ext_ffi_api.html">ffi.* API</a> |
40 | </li><li> | 40 | </li><li> |
41 | <a href="ext_ffi_int64.html">64 bit Integers</a> | ||
42 | </li><li> | ||
43 | <a href="ext_ffi_semantics.html">FFI Semantics</a> | 41 | <a href="ext_ffi_semantics.html">FFI Semantics</a> |
44 | </li></ul> | 42 | </li></ul> |
45 | </li><li> | 43 | </li><li> |
@@ -106,7 +104,7 @@ follows: | |||
106 | </p> | 104 | </p> |
107 | <pre class="code"> | 105 | <pre class="code"> |
108 | ffi.cdef[[ | 106 | ffi.cdef[[ |
109 | <span style="color:#00a000;font-weight:bold;">typedef struct foo { int a, b; } foo_t; // Declare a struct and typedef. | 107 | <span style="color:#00a000;">typedef struct foo { int a, b; } foo_t; // Declare a struct and typedef. |
110 | int dofoo(foo_t *f, int n); /* Declare an external C function. */</span> | 108 | int dofoo(foo_t *f, int n); /* Declare an external C function. */</span> |
111 | ]] | 109 | ]] |
112 | </pre> | 110 | </pre> |
@@ -237,12 +235,8 @@ rules</a>. | |||
237 | </p> | 235 | </p> |
238 | <p> | 236 | <p> |
239 | This functions is mainly useful to override the pointer compatibility | 237 | This functions is mainly useful to override the pointer compatibility |
240 | rules or to convert pointers to addresses or vice versa. For maximum | 238 | checks or to convert pointers to addresses or vice versa. |
241 | portability you should convert a pointer to its address as follows: | ||
242 | </p> | 239 | </p> |
243 | <pre class="code"> | ||
244 | local addr = tonumber(ffi.cast("intptr_t", ptr)) | ||
245 | </pre> | ||
246 | 240 | ||
247 | <h2 id="info">C Type Information</h2> | 241 | <h2 id="info">C Type Information</h2> |
248 | <p> | 242 | <p> |
@@ -383,6 +377,45 @@ Contains the target OS name. Same contents as | |||
383 | Contains the target architecture name. Same contents as | 377 | Contains the target architecture name. Same contents as |
384 | <a href="ext_jit.html#jit_arch"><tt>jit.arch</tt></a>. | 378 | <a href="ext_jit.html#jit_arch"><tt>jit.arch</tt></a>. |
385 | </p> | 379 | </p> |
380 | |||
381 | <h2 id="extended">Extended Standard Library Functions</h2> | ||
382 | <p> | ||
383 | The following standard library functions have been extended to work | ||
384 | with cdata objects: | ||
385 | </p> | ||
386 | |||
387 | <h3 id="tonumber"><tt>n = tonumber(cdata)</tt></h3> | ||
388 | <p> | ||
389 | Converts a number cdata object to a <tt>double</tt> and returns it as | ||
390 | a Lua number. This is particularly useful for boxed 64 bit | ||
391 | integer values. Caveat: this conversion may incur a precision loss. | ||
392 | </p> | ||
393 | |||
394 | <h3 id="tostring"><tt>s = tostring(cdata)</tt></h3> | ||
395 | <p> | ||
396 | Returns a string representation of the value of 64 bit integers | ||
397 | (<tt><b>"</b>nnn<b>LL"</b></tt> or <tt><b>"</b>nnn<b>ULL"</b></tt>) or | ||
398 | complex numbers (<tt><b>"</b>re±im<b>i"</b></tt>). Otherwise | ||
399 | returns a string representation of the C type of a ctype object | ||
400 | (<tt><b>"ctype<</b>type<b>>"</b></tt>) or a cdata object | ||
401 | (<tt><b>"cdata<</b>type<b>>: </b>address"</tt>). | ||
402 | </p> | ||
403 | |||
404 | <h2 id="literals">Extensions to the Lua Parser</h2> | ||
405 | <p> | ||
406 | The parser for Lua source code treats numeric literals with the | ||
407 | suffixes <tt>LL</tt> or <tt>ULL</tt> as signed or unsigned 64 bit | ||
408 | integers. Case doesn't matter, but uppercase is recommended for | ||
409 | readability. It handles both decimal (<tt>42LL</tt>) and hexadecimal | ||
410 | (<tt>0x2aLL</tt>) literals. | ||
411 | </p> | ||
412 | <p> | ||
413 | The imaginary part of complex numbers can be specified by suffixing | ||
414 | number literals with <tt>i</tt> or <tt>I</tt>, e.g. <tt>12.5i</tt>. | ||
415 | Caveat: you'll need to use <tt>1i</tt> to get an imaginary part with | ||
416 | the value one, since <tt>i</tt> itself still refers to a variable | ||
417 | named <tt>i</tt>. | ||
418 | </p> | ||
386 | <br class="flush"> | 419 | <br class="flush"> |
387 | </div> | 420 | </div> |
388 | <div id="foot"> | 421 | <div id="foot"> |
diff --git a/doc/ext_ffi_int64.html b/doc/ext_ffi_int64.html deleted file mode 100644 index fa155825..00000000 --- a/doc/ext_ffi_int64.html +++ /dev/null | |||
@@ -1,73 +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>64 bit Integers</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>64 bit Integers</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 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 class="current" 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">»</span></a> | ||
54 | </li><li> | ||
55 | <a href="http://luajit.org/download.html">Download <span class="ext">»</span></a> | ||
56 | </li></ul> | ||
57 | </div> | ||
58 | <div id="main"> | ||
59 | <p> | ||
60 | TODO | ||
61 | </p> | ||
62 | <br class="flush"> | ||
63 | </div> | ||
64 | <div id="foot"> | ||
65 | <hr class="hide"> | ||
66 | Copyright © 2005-2011 Mike Pall | ||
67 | <span class="noprint"> | ||
68 | · | ||
69 | <a href="contact.html">Contact</a> | ||
70 | </span> | ||
71 | </div> | ||
72 | </body> | ||
73 | </html> | ||
diff --git a/doc/ext_ffi_semantics.html b/doc/ext_ffi_semantics.html index b2b3af30..69dfc2ca 100644 --- a/doc/ext_ffi_semantics.html +++ b/doc/ext_ffi_semantics.html | |||
@@ -39,8 +39,6 @@ td.convop { font-style: italic; width: 16em; } | |||
39 | </li><li> | 39 | </li><li> |
40 | <a href="ext_ffi_api.html">ffi.* API</a> | 40 | <a href="ext_ffi_api.html">ffi.* API</a> |
41 | </li><li> | 41 | </li><li> |
42 | <a href="ext_ffi_int64.html">64 bit Integers</a> | ||
43 | </li><li> | ||
44 | <a class="current" href="ext_ffi_semantics.html">FFI Semantics</a> | 42 | <a class="current" href="ext_ffi_semantics.html">FFI Semantics</a> |
45 | </li></ul> | 43 | </li></ul> |
46 | </li><li> | 44 | </li><li> |
@@ -653,7 +651,10 @@ parameters given by the function declaration. Arguments passed to the | |||
653 | variable argument part of vararg C function use | 651 | variable argument part of vararg C function use |
654 | <a href="#convert_vararg">special conversion rules</a>. This | 652 | <a href="#convert_vararg">special conversion rules</a>. This |
655 | C function is called and the return value (if any) is | 653 | C function is called and the return value (if any) is |
656 | <a href="#convert_tolua">converted to a Lua object</a>.</li> | 654 | <a href="#convert_tolua">converted to a Lua object</a>.<br> |
655 | On Windows/x86 systems, <tt>stdcall</tt> functions are automatically | ||
656 | detected and a function declared as <tt>cdecl</tt> (the default) is | ||
657 | silently fixed up after the first call.</li> | ||
657 | 658 | ||
658 | </ul> | 659 | </ul> |
659 | 660 | ||
@@ -672,15 +673,24 @@ can be subtracted. The result is the difference between their | |||
672 | addresses, divided by the element size in bytes. An error is raised if | 673 | addresses, divided by the element size in bytes. An error is raised if |
673 | the element size is undefined or zero.</li> | 674 | the element size is undefined or zero.</li> |
674 | 675 | ||
675 | <li><a href="ext_ffi_int64.html">64 bit integer arithmetic</a>: | 676 | <li><b>64 bit integer arithmetic</b>: the standard arithmetic |
676 | the standard arithmetic operators | 677 | operators (<tt>+ - * / % ^</tt> and unary |
677 | (<tt>+ - * / % ^</tt> and unary <tt>-</tt>) | 678 | minus) can be applied to two cdata numbers, or a cdata number and a |
678 | can be applied to two cdata numbers, or a cdata number and a Lua | 679 | Lua number. If one of them is an <tt>uint64_t</tt>, the other side is |
679 | number. If one of them is an <tt>uint64_t</tt>, the other side is | ||
680 | converted to an <tt>uint64_t</tt> and an unsigned arithmetic operation | 680 | converted to an <tt>uint64_t</tt> and an unsigned arithmetic operation |
681 | is performed. Otherwise both sides are converted to an | 681 | is performed. Otherwise both sides are converted to an |
682 | <tt>int64_t</tt> and a signed arithmetic operation is performed. The | 682 | <tt>int64_t</tt> and a signed arithmetic operation is performed. The |
683 | result is a boxed 64 bit cdata object.</li> | 683 | result is a boxed 64 bit cdata object.<br> |
684 | |||
685 | These rules ensure that 64 bit integers are "sticky". Any | ||
686 | expression involving at least one 64 bit integer operand results | ||
687 | in another one. The undefined cases for the division, modulo and power | ||
688 | operators return <tt>2LL ^ 63</tt> or | ||
689 | <tt>2ULL ^ 63</tt>.<br> | ||
690 | |||
691 | You'll have to explicitly convert a 64 bit integer to a Lua | ||
692 | number (e.g. for regular floating-point calculations) with | ||
693 | <tt>tonumber()</tt>. But note this may incur a precision loss.</li> | ||
684 | 694 | ||
685 | </ul> | 695 | </ul> |
686 | 696 | ||
@@ -692,12 +702,12 @@ can be compared. The result is the same as an unsigned comparison of | |||
692 | their addresses. <tt>nil</tt> is treated like a <tt>NULL</tt> pointer, | 702 | their addresses. <tt>nil</tt> is treated like a <tt>NULL</tt> pointer, |
693 | which is compatible with any other pointer type.</li> | 703 | which is compatible with any other pointer type.</li> |
694 | 704 | ||
695 | <li><a href="ext_ffi_int64.html">64 bit integer comparison</a>: | 705 | <li><b>64 bit integer comparison</b>: two cdata numbers, or a |
696 | two cdata numbers, or a cdata number and a Lua number can be compared | 706 | cdata number and a Lua number can be compared with each other. If one |
697 | with each other. If one of them is an <tt>uint64_t</tt>, the other | 707 | of them is an <tt>uint64_t</tt>, the other side is converted to an |
698 | side is converted to an <tt>uint64_t</tt> and an unsigned comparison | 708 | <tt>uint64_t</tt> and an unsigned comparison is performed. Otherwise |
699 | is performed. Otherwise both sides are converted to an | 709 | both sides are converted to an <tt>int64_t</tt> and a signed |
700 | <tt>int64_t</tt> and a signed comparison is performed.</li> | 710 | comparison is performed.</li> |
701 | 711 | ||
702 | </ul> | 712 | </ul> |
703 | 713 | ||
diff --git a/doc/ext_ffi_tutorial.html b/doc/ext_ffi_tutorial.html index 11e83339..c43b223b 100644 --- a/doc/ext_ffi_tutorial.html +++ b/doc/ext_ffi_tutorial.html | |||
@@ -8,6 +8,13 @@ | |||
8 | <meta name="Language" content="en"> | 8 | <meta name="Language" content="en"> |
9 | <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> | 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"> | 10 | <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> |
11 | <style type="text/css"> | ||
12 | table.idiomtable { line-height: 1.2; } | ||
13 | tr.idiomhead td { font-weight: bold; } | ||
14 | td.idiomc { width: 12em; } | ||
15 | td.idiomlua { width: 14em; } | ||
16 | td.idiomlua b { font-weight: normal; color: #2142bf; } | ||
17 | </style> | ||
11 | </head> | 18 | </head> |
12 | <body> | 19 | <body> |
13 | <div id="site"> | 20 | <div id="site"> |
@@ -33,8 +40,6 @@ | |||
33 | </li><li> | 40 | </li><li> |
34 | <a href="ext_ffi_api.html">ffi.* API</a> | 41 | <a href="ext_ffi_api.html">ffi.* API</a> |
35 | </li><li> | 42 | </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> | 43 | <a href="ext_ffi_semantics.html">FFI Semantics</a> |
39 | </li></ul> | 44 | </li></ul> |
40 | </li><li> | 45 | </li><li> |
@@ -57,7 +62,14 @@ | |||
57 | </div> | 62 | </div> |
58 | <div id="main"> | 63 | <div id="main"> |
59 | <p> | 64 | <p> |
60 | TODO | 65 | This page is intended to give you an overview of the features of the FFI |
66 | library by presenting a few use cases and guidelines. | ||
67 | </p> | ||
68 | <p> | ||
69 | This page makes no attempt to explain all of the FFI library, though. | ||
70 | You'll want to have a look at the <a href="ext_ffi_api.html">ffi.* API | ||
71 | function reference</a> and the <a href="ext_ffi_semantics.html">FFI | ||
72 | semantics</a> to learn more. | ||
61 | </p> | 73 | </p> |
62 | 74 | ||
63 | <h2 id="load">Loading the FFI Library</h2> | 75 | <h2 id="load">Loading the FFI Library</h2> |
@@ -76,7 +88,339 @@ of globals — you really need to use the local variable. The | |||
76 | <tt>require</tt> function ensures the library is only loaded once. | 88 | <tt>require</tt> function ensures the library is only loaded once. |
77 | </p> | 89 | </p> |
78 | 90 | ||
79 | <h2>TODO</h2> | 91 | <h2 id="sleep">Accessing Standard System Functions</h2> |
92 | <p> | ||
93 | The following code explains how to access standard system functions. | ||
94 | We slowly print two lines of dots by sleeping for 10 milliseconds | ||
95 | after each dot: | ||
96 | </p> | ||
97 | <pre class="code"> | ||
98 | local ffi = require("ffi") | ||
99 | ffi.cdef[[ <span style="color:#f0f4ff;">//</span><span style="color:#4040c0;">①</span> | ||
100 | <span style="color:#00a000;">void Sleep(int ms); | ||
101 | int poll(struct pollfd *fds, unsigned long nfds, int timeout);</span> | ||
102 | ]] | ||
103 | |||
104 | local sleep | ||
105 | if ffi.os == "Windows" then <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">②</span> | ||
106 | function sleep(s) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">③</span> | ||
107 | ffi.C.Sleep(s*1000) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">④</span> | ||
108 | end | ||
109 | else | ||
110 | function sleep(s) | ||
111 | ffi.C.poll(nil, 0, s*1000) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">⑤</span> | ||
112 | end | ||
113 | end | ||
114 | |||
115 | for i=1,160 do | ||
116 | io.write("."); io.flush() | ||
117 | sleep(0.01) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">⑥</span> | ||
118 | end | ||
119 | io.write("\n") | ||
120 | </pre> | ||
121 | <p> | ||
122 | Here's the step-by-step explanation: | ||
123 | </p> | ||
124 | <p> | ||
125 | <span style="color:#4040c0;">①</span> This defines the | ||
126 | C library functions we're going to use. The part inside the | ||
127 | double-brackets (in green) is just standard C syntax. You can | ||
128 | usually get this info from the C header files or the | ||
129 | documentation provided by each C library or C compiler. | ||
130 | </p> | ||
131 | <p> | ||
132 | <span style="color:#4040c0;">②</span> The difficulty we're | ||
133 | facing here, is that there are different standards to choose from. | ||
134 | Windows has a simple <tt>Sleep()</tt> function. On other systems there | ||
135 | are a variety of functions available to achieve sub-second sleeps, but | ||
136 | with no clear consensus. Thankfully <tt>poll()</tt> can be used for | ||
137 | this task, too, and it's present on most non-Windows systems. The | ||
138 | check for <tt>ffi.os</tt> makes sure we use the Windows-specific | ||
139 | function only on Windows systems. | ||
140 | </p> | ||
141 | <p> | ||
142 | <span style="color:#4040c0;">③</span> Here we're wrapping the | ||
143 | call to the C function in a Lua function. This isn't strictly | ||
144 | necessary, but it's helpful to deal with system-specific issues only | ||
145 | in one part of the code. The way we're wrapping it ensures the check | ||
146 | for the OS is only done during initialization and not for every call. | ||
147 | </p> | ||
148 | <p> | ||
149 | <span style="color:#4040c0;">④</span> A more subtle point is | ||
150 | that we defined our <tt>sleep()</tt> function (for the sake of this | ||
151 | example) as taking the number of seconds, but accepting fractional | ||
152 | seconds. Multiplying this by 1000 gets us milliseconds, but that still | ||
153 | leaves it a Lua number, which is a floating-point value. Alas, the | ||
154 | <tt>Sleep()</tt> function only accepts an integer value. Luckily for | ||
155 | us, the FFI library automatically performs the conversion when calling | ||
156 | the function (truncating the FP value towards zero, like in C). | ||
157 | </p> | ||
158 | <p style="font-size: 8pt;"> | ||
159 | Some readers will notice that <tt>Sleep()</tt> is part of | ||
160 | <tt>KERNEL32.DLL</tt> and is also a <tt>stdcall</tt> function. So how | ||
161 | can this possibly work? The FFI library provides the <tt>ffi.C</tt> | ||
162 | default C library namespace, which allows calling functions from | ||
163 | the default set of libraries, like a C compiler would. Also, the | ||
164 | FFI library automatically detects <tt>stdcall</tt> functions, so you | ||
165 | don't need to declare them as such. | ||
166 | </p> | ||
167 | <p> | ||
168 | <span style="color:#4040c0;">⑤</span> The <tt>poll()</tt> | ||
169 | function takes a couple more arguments we're not going to use. You can | ||
170 | simply use <tt>nil</tt> to pass a <tt>NULL</tt> pointer and <tt>0</tt> | ||
171 | for the <tt>nfds</tt> parameter. Please note that the | ||
172 | number <tt>0</tt> <em>does not convert to a pointer value</em>, | ||
173 | unlike in C++. You really have to pass pointers to pointer arguments | ||
174 | and numbers to number arguments. | ||
175 | </p> | ||
176 | <p style="font-size: 8pt;"> | ||
177 | The page on <a href="ext_ffi_semantics.html">FFI semantics</a> has all | ||
178 | of the gory details about | ||
179 | <a href="ext_ffi_semantics.html#convert">conversions between Lua | ||
180 | objects and C types</a>. For the most part you don't have to deal | ||
181 | with this, as it's performed automatically and it's carefully designed | ||
182 | to bridge the semantic differences between Lua and C. | ||
183 | </p> | ||
184 | <p> | ||
185 | <span style="color:#4040c0;">⑥</span> Now that we have defined | ||
186 | our own <tt>sleep()</tt> function, we can just call it from plain Lua | ||
187 | code. That wasn't so bad, huh? Turning these boring animated dots into | ||
188 | a fascinating best-selling game is left as an exercise for the reader. | ||
189 | :-) | ||
190 | </p> | ||
191 | |||
192 | <h2 id="zlib">Accessing the zlib Compression Library</h2> | ||
193 | <p> | ||
194 | The following code shows how to access the <a | ||
195 | href="http://zlib.net/">zlib</a> compression library from Lua code. | ||
196 | We'll define two convenience wrapper functions that take a string and | ||
197 | compress or uncompress it to another string: | ||
198 | </p> | ||
199 | <pre class="code"> | ||
200 | local ffi = require("ffi") | ||
201 | ffi.cdef[[ <span style="color:#f0f4ff;">//</span><span style="color:#4040c0;">①</span> | ||
202 | <span style="color:#00a000;">unsigned long compressBound(unsigned long sourceLen); | ||
203 | int compress2(uint8_t *dest, unsigned long *destLen, | ||
204 | const uint8_t *source, unsigned long sourceLen, int level); | ||
205 | int uncompress(uint8_t *dest, unsigned long *destLen, | ||
206 | const uint8_t *source, unsigned long sourceLen);</span> | ||
207 | ]] | ||
208 | local zlib = ffi.load(ffi.os == "Windows" and "zlib1" or "z") <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">②</span> | ||
209 | |||
210 | local function compress(txt) | ||
211 | local n = zlib.compressBound(#txt) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">③</span> | ||
212 | local buf = ffi.new("uint8_t[?]", n) | ||
213 | local buflen = ffi.new("unsigned long[1]", n) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">④</span> | ||
214 | local res = zlib.compress2(buf, buflen, txt, #txt, 9) | ||
215 | assert(res == 0) | ||
216 | return ffi.string(buf, buflen[0]) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">⑤</span> | ||
217 | end | ||
218 | |||
219 | local function uncompress(comp, n) <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">⑥</span> | ||
220 | local buf = ffi.new("uint8_t[?]", n) | ||
221 | local buflen = ffi.new("unsigned long[1]", n) | ||
222 | local res = zlib.uncompress(buf, buflen, comp, #comp) | ||
223 | assert(res == 0) | ||
224 | return ffi.string(buf, buflen[0]) | ||
225 | end | ||
226 | |||
227 | -- Simple test code. <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">⑦</span> | ||
228 | local txt = string.rep("abcd", 1000) | ||
229 | print("Uncompressed size: ", #txt) | ||
230 | local c = compress(txt) | ||
231 | print("Compressed size: ", #c) | ||
232 | local txt2 = uncompress(c, #txt) | ||
233 | assert(txt2 == txt) | ||
234 | </pre> | ||
235 | <p> | ||
236 | Here's the step-by-step explanation: | ||
237 | </p> | ||
238 | <p> | ||
239 | <span style="color:#4040c0;">①</span> This defines some of the | ||
240 | C functions provided by zlib. For the sake of this example, some | ||
241 | type indirections have been reduced and it uses the pre-defined | ||
242 | fixed-size integer types, while still adhering to the zlib API/ABI. | ||
243 | </p> | ||
244 | <p> | ||
245 | <span style="color:#4040c0;">②</span> This loads the zlib shared | ||
246 | library. On POSIX systems it's named <tt>libz.so</tt> and usually | ||
247 | comes pre-installed. Since <tt>ffi.load()</tt> automatically adds any | ||
248 | missing standard prefixes/suffixes, we can simply load the | ||
249 | <tt>"z"</tt> library. On Windows it's named <tt>zlib1.dll</tt> and | ||
250 | you'll have to download it first from the | ||
251 | <a href="http://zlib.net/"><span class="ext">»</span> zlib site</a>. The check for | ||
252 | <tt>ffi.os</tt> makes sure we pass the right name to | ||
253 | <tt>ffi.load()</tt>. | ||
254 | </p> | ||
255 | <p> | ||
256 | <span style="color:#4040c0;">③</span> First, the maximum size of | ||
257 | the compression buffer is obtained by calling the | ||
258 | <tt>zlib.compressBound</tt> function with the length of the | ||
259 | uncompressed string. The next line allocates a byte buffer of this | ||
260 | size. The <tt>[?]</tt> in the type specification indicates a | ||
261 | variable-length array (VLA). The actual number of elements of this | ||
262 | array is given as the 2nd argument to <tt>ffi.new()</tt>. | ||
263 | </p> | ||
264 | <p> | ||
265 | <span style="color:#4040c0;">④</span> This may look strange at | ||
266 | first, but have a look at the declaration of the <tt>compress2</tt> | ||
267 | function from zlib: the destination length is defined as a pointer! | ||
268 | This is because you pass in the maximum buffer size and get back the | ||
269 | actual length that was used. | ||
270 | </p> | ||
271 | <p> | ||
272 | In C you'd pass in the address of a local variable | ||
273 | (<tt>&buflen</tt>). But since there's no address-of operator in | ||
274 | Lua, we'll just pass in a one-element array. Conveniently it can be | ||
275 | initialized with the maximum buffer size in one step. Calling the | ||
276 | actual <tt>zlib.compress2</tt> function is then straightforward. | ||
277 | </p> | ||
278 | <p> | ||
279 | <span style="color:#4040c0;">⑤</span> We want to return the | ||
280 | compressed data as a Lua string, so we'll use <tt>ffi.string()</tt>. | ||
281 | It needs a pointer to the start of the data and the actual length. The | ||
282 | length has been returned in the <tt>buflen</tt> array, so we'll just | ||
283 | get it from there. | ||
284 | </p> | ||
285 | <p style="font-size: 8pt;"> | ||
286 | Note that since the function returns now, the <tt>buf</tt> and | ||
287 | <tt>buflen</tt> variables will eventually be garbage collected. This | ||
288 | is fine, because <tt>ffi.string()</tt> has copied the contents to a | ||
289 | newly created (interned) Lua string. If you plan to call this function | ||
290 | lots of times, consider reusing the buffers and/or handing back the | ||
291 | results in buffers instead of strings. This will reduce the overhead | ||
292 | for garbage collection and string interning. | ||
293 | </p> | ||
294 | <p> | ||
295 | <span style="color:#4040c0;">⑥</span> The <tt>uncompress</tt> | ||
296 | functions does the exact opposite of the <tt>compress</tt> function. | ||
297 | The compressed data doesn't include the size of the original string, | ||
298 | so this needs to be passed in. Otherwise no surprises here. | ||
299 | </p> | ||
300 | <p> | ||
301 | <span style="color:#4040c0;">⑦</span> The code, that makes use | ||
302 | of the functions we just defined, is just plain Lua code. It doesn't | ||
303 | need to know anything about the LuaJIT FFI — the convenience | ||
304 | wrapper functions completely hide it. | ||
305 | </p> | ||
306 | <p> | ||
307 | One major advantage of the LuaJIT FFI is that you are now able to | ||
308 | write those wrappers <em>in Lua</em>. And at a fraction of the time it | ||
309 | would cost you to create an extra C module using the Lua/C API. | ||
310 | Many of the simpler C functions can probably be used directly | ||
311 | from your Lua code, without any wrappers. | ||
312 | </p> | ||
313 | <p style="font-size: 8pt;"> | ||
314 | Side note: the zlib API uses the <tt>long</tt> type for passing | ||
315 | lengths and sizes around. But all those zlib functions actually only | ||
316 | deal with 32 bit values. This is an unfortunate choice for a | ||
317 | public API, but may be explained by zlib's history — we'll just | ||
318 | have to deal with it. | ||
319 | </p> | ||
320 | <p style="font-size: 8pt;"> | ||
321 | First, you should know that a <tt>long</tt> is a 64 bit type e.g. | ||
322 | on POSIX/x64 systems, but a 32 bit type on Windows/x64 and on | ||
323 | 32 bit systems. Thus a <tt>long</tt> result can be either a plain | ||
324 | Lua number or a boxed 64 bit integer cdata object, depending on | ||
325 | the target system. | ||
326 | </p> | ||
327 | <p style="font-size: 8pt;"> | ||
328 | Ok, so the <tt>ffi.*</tt> functions generally accept cdata objects | ||
329 | wherever you'd want to use a number. That's why we get a away with | ||
330 | passing <tt>n</tt> to <tt>ffi.string()</tt> above. But other Lua | ||
331 | library functions or modules don't know how to deal with this. So for | ||
332 | maximum portability one needs to use <tt>tonumber()</tt> on returned | ||
333 | <tt>long</tt> results before passing them on. Otherwise the | ||
334 | application might work on some systems, but would fail in a POSIX/x64 | ||
335 | environment. | ||
336 | </p> | ||
337 | |||
338 | <h2 id="idioms">Translating C Idioms</h2> | ||
339 | <p> | ||
340 | Here's a list of common C idioms and their translation to the | ||
341 | LuaJIT FFI: | ||
342 | </p> | ||
343 | <table class="idiomtable"> | ||
344 | <tr class="idiomhead"> | ||
345 | <td class="idiomdesc">Idiom</td> | ||
346 | <td class="idiomc">C code</td> | ||
347 | <td class="idiomlua">Lua code</td> | ||
348 | </tr> | ||
349 | <tr class="odd separate"> | ||
350 | <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> | ||
351 | <tr class="even"> | ||
352 | <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> | ||
353 | <tr class="odd"> | ||
354 | <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> | ||
355 | <tr class="even separate"> | ||
356 | <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> | ||
357 | <tr class="odd"> | ||
358 | <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> | ||
359 | <tr class="even separate"> | ||
360 | <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> | ||
361 | <tr class="odd"> | ||
362 | <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> | ||
363 | <tr class="even"> | ||
364 | <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> | ||
365 | <tr class="odd"> | ||
366 | <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> | ||
367 | <tr class="even separate"> | ||
368 | <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> | ||
369 | <tr class="odd"> | ||
370 | <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> | ||
371 | </table> | ||
372 | |||
373 | <h2 id="cache">To Cache or Not to Cache</h2> | ||
374 | <p> | ||
375 | It's a common Lua idiom to cache library functions in local variables | ||
376 | or upvalues, e.g.: | ||
377 | </p> | ||
378 | <pre class="code"> | ||
379 | local byte, char = string.byte, string.char | ||
380 | local function foo(x) | ||
381 | return char(byte(x)+1) | ||
382 | end | ||
383 | </pre> | ||
384 | <p> | ||
385 | This replaces several hash-table lookups with a (faster) direct use of | ||
386 | a local or an upvalue. This is less important with LuaJIT, since the | ||
387 | JIT compiler optimizes hash-table lookups a lot and is even able to | ||
388 | hoist most of them out of the inner loops. It can't eliminate | ||
389 | <em>all</em> of them, though, and it saves some typing for often-used | ||
390 | functions. So there's still a place for this, even with LuaJIT. | ||
391 | </p> | ||
392 | <p> | ||
393 | The situation is a bit different with C function calls via the | ||
394 | FFI library. The JIT compiler has special logic to eliminate <em>all | ||
395 | of the lookup overhead</em> for functions resolved from a | ||
396 | <a href="ext_ffi_semantics.html#clib">C library namespace</a>! | ||
397 | Thus it's not helpful and actually counter-productive to cache | ||
398 | individual C functions like this: | ||
399 | </p> | ||
400 | <pre class="code"> | ||
401 | local <b>funca</b>, <b>funcb</b> = ffi.C.funcb, ffi.C.funcb -- <span style="color:#c00000;">Not helpful!</span> | ||
402 | local function foo(x, n) | ||
403 | for i=1,n do <b>funcb</b>(<b>funca</b>(x, i), 1) end | ||
404 | end | ||
405 | </pre> | ||
406 | <p> | ||
407 | This turns them into indirect calls and generates bigger and slower | ||
408 | machine code. Instead you'll want to cache the namespace itself and | ||
409 | rely on the JIT compiler to eliminate the lookups: | ||
410 | </p> | ||
411 | <pre class="code"> | ||
412 | local <b>C</b> = ffi.C -- <span style="color:#00a000;">Instead use this!</span> | ||
413 | local function foo(x, n) | ||
414 | for i=1,n do <b>C.funcb</b>(<b>C.funca</b>(x, i), 1) end | ||
415 | end | ||
416 | </pre> | ||
417 | <p> | ||
418 | This generates both shorter and faster code. So <b>don't cache | ||
419 | C functions</b>, but <b>do</b> cache namespaces! Most often the | ||
420 | namespace is already in a local variable at an outer scope, e.g. from | ||
421 | <tt>local lib = ffi.load(...)</tt>. Note that copying | ||
422 | it to a local variable in the function scope is unnecessary. | ||
423 | </p> | ||
80 | <br class="flush"> | 424 | <br class="flush"> |
81 | </div> | 425 | </div> |
82 | <div id="foot"> | 426 | <div id="foot"> |
diff --git a/doc/ext_jit.html b/doc/ext_jit.html index 36e306a8..e8f5518e 100644 --- a/doc/ext_jit.html +++ b/doc/ext_jit.html | |||
@@ -33,8 +33,6 @@ | |||
33 | </li><li> | 33 | </li><li> |
34 | <a href="ext_ffi_api.html">ffi.* API</a> | 34 | <a href="ext_ffi_api.html">ffi.* API</a> |
35 | </li><li> | 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> | 36 | <a href="ext_ffi_semantics.html">FFI Semantics</a> |
39 | </li></ul> | 37 | </li></ul> |
40 | </li><li> | 38 | </li><li> |
diff --git a/doc/extensions.html b/doc/extensions.html index 8385727b..7d12299c 100644 --- a/doc/extensions.html +++ b/doc/extensions.html | |||
@@ -50,8 +50,6 @@ td.excinterop { | |||
50 | </li><li> | 50 | </li><li> |
51 | <a href="ext_ffi_api.html">ffi.* API</a> | 51 | <a href="ext_ffi_api.html">ffi.* API</a> |
52 | </li><li> | 52 | </li><li> |
53 | <a href="ext_ffi_int64.html">64 bit Integers</a> | ||
54 | </li><li> | ||
55 | <a href="ext_ffi_semantics.html">FFI Semantics</a> | 53 | <a href="ext_ffi_semantics.html">FFI Semantics</a> |
56 | </li></ul> | 54 | </li></ul> |
57 | </li><li> | 55 | </li><li> |
diff --git a/doc/faq.html b/doc/faq.html index 4ec69882..8de8c3f1 100644 --- a/doc/faq.html +++ b/doc/faq.html | |||
@@ -36,8 +36,6 @@ dd { margin-left: 1.5em; } | |||
36 | </li><li> | 36 | </li><li> |
37 | <a href="ext_ffi_api.html">ffi.* API</a> | 37 | <a href="ext_ffi_api.html">ffi.* API</a> |
38 | </li><li> | 38 | </li><li> |
39 | <a href="ext_ffi_int64.html">64 bit Integers</a> | ||
40 | </li><li> | ||
41 | <a href="ext_ffi_semantics.html">FFI Semantics</a> | 39 | <a href="ext_ffi_semantics.html">FFI Semantics</a> |
42 | </li></ul> | 40 | </li></ul> |
43 | </li><li> | 41 | </li><li> |
diff --git a/doc/install.html b/doc/install.html index 55de1bd8..220c326f 100644 --- a/doc/install.html +++ b/doc/install.html | |||
@@ -62,8 +62,6 @@ td.compatno { | |||
62 | </li><li> | 62 | </li><li> |
63 | <a href="ext_ffi_api.html">ffi.* API</a> | 63 | <a href="ext_ffi_api.html">ffi.* API</a> |
64 | </li><li> | 64 | </li><li> |
65 | <a href="ext_ffi_int64.html">64 bit Integers</a> | ||
66 | </li><li> | ||
67 | <a href="ext_ffi_semantics.html">FFI Semantics</a> | 65 | <a href="ext_ffi_semantics.html">FFI Semantics</a> |
68 | </li></ul> | 66 | </li></ul> |
69 | </li><li> | 67 | </li><li> |
diff --git a/doc/luajit.html b/doc/luajit.html index 131e4396..108ca18e 100644 --- a/doc/luajit.html +++ b/doc/luajit.html | |||
@@ -34,8 +34,6 @@ | |||
34 | </li><li> | 34 | </li><li> |
35 | <a href="ext_ffi_api.html">ffi.* API</a> | 35 | <a href="ext_ffi_api.html">ffi.* API</a> |
36 | </li><li> | 36 | </li><li> |
37 | <a href="ext_ffi_int64.html">64 bit Integers</a> | ||
38 | </li><li> | ||
39 | <a href="ext_ffi_semantics.html">FFI Semantics</a> | 37 | <a href="ext_ffi_semantics.html">FFI Semantics</a> |
40 | </li></ul> | 38 | </li></ul> |
41 | </li><li> | 39 | </li><li> |
diff --git a/doc/running.html b/doc/running.html index cb96eabb..ba55e56d 100644 --- a/doc/running.html +++ b/doc/running.html | |||
@@ -55,8 +55,6 @@ td.param_default { | |||
55 | </li><li> | 55 | </li><li> |
56 | <a href="ext_ffi_api.html">ffi.* API</a> | 56 | <a href="ext_ffi_api.html">ffi.* API</a> |
57 | </li><li> | 57 | </li><li> |
58 | <a href="ext_ffi_int64.html">64 bit Integers</a> | ||
59 | </li><li> | ||
60 | <a href="ext_ffi_semantics.html">FFI Semantics</a> | 58 | <a href="ext_ffi_semantics.html">FFI Semantics</a> |
61 | </li></ul> | 59 | </li></ul> |
62 | </li><li> | 60 | </li><li> |
diff --git a/doc/status.html b/doc/status.html index 5ce3bf4c..eddbfb24 100644 --- a/doc/status.html +++ b/doc/status.html | |||
@@ -36,8 +36,6 @@ ul li { padding-bottom: 0.3em; } | |||
36 | </li><li> | 36 | </li><li> |
37 | <a href="ext_ffi_api.html">ffi.* API</a> | 37 | <a href="ext_ffi_api.html">ffi.* API</a> |
38 | </li><li> | 38 | </li><li> |
39 | <a href="ext_ffi_int64.html">64 bit Integers</a> | ||
40 | </li><li> | ||
41 | <a href="ext_ffi_semantics.html">FFI Semantics</a> | 39 | <a href="ext_ffi_semantics.html">FFI Semantics</a> |
42 | </li></ul> | 40 | </li></ul> |
43 | </li><li> | 41 | </li><li> |