diff options
Diffstat (limited to 'doc/ext_ffi.html')
-rw-r--r-- | doc/ext_ffi.html | 92 |
1 files changed, 55 insertions, 37 deletions
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 |