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 | |
| parent | a2f9f1f831c77b19433b9f8858b9c1db0e421800 (diff) | |
| download | luajit-a5aade2fa9ff89f9f3c4a91261071299de0d0fa4.tar.gz luajit-a5aade2fa9ff89f9f3c4a91261071299de0d0fa4.tar.bz2 luajit-a5aade2fa9ff89f9f3c4a91261071299de0d0fa4.zip | |
FFI: Finish FFI docs.
| -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> |
