summaryrefslogtreecommitdiff
path: root/doc/ext_ffi.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/ext_ffi.html')
-rw-r--r--doc/ext_ffi.html92
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.
86It's really easy to call an external C&nbsp;library function: 84It's really easy to call an external C&nbsp;library function:
87</p> 85</p>
88<pre class="code"> 86<pre class="code">
89<span style="color:#000080;">local ffi = require("ffi")</span> 87local ffi = require("ffi") <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">&#9312;</span>
90ffi.cdef[[ 88ffi.cdef[[ <span style="color:#f0f4ff;">//</span><span style="color:#4040c0;">&#9313;</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") 91ffi.C.printf("Hello %s!", "world") <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">&#9314;</span>
94</pre> 92</pre>
95<p> 93<p>
96So, let's pick that apart: the first line (in blue) loads the FFI 94So, let's pick that apart:
97library. The next one adds a C&nbsp;declaration for the function. The 95</p>
98part between the double-brackets (in green) is just standard 96<p>
99C&nbsp;syntax. And the last line calls the named C&nbsp;function. Yes, 97<span style="color:#4040c0;">&#9312;</span> Load the FFI library.
100it's that simple! 98</p>
99<p>
100<span style="color:#4040c0;">&#9313;</span> Add a C&nbsp;declaration
101for the function. The part inside the double-brackets (in green) is
102just standard C&nbsp;syntax.
103</p>
104<p>
105<span style="color:#4040c0;">&#9314;</span> Call the named
106C&nbsp;function &mdash; Yes, it's that simple!
101</p> 107</p>
102<p style="font-size: 8pt;"> 108<p style="font-size: 8pt;">
103Actually, what goes on behind the scenes is far from simple: the first 109Actually, what goes on behind the scenes is far from simple: <span
104part of the last line (in orange) makes use of the standard 110style="color:#4040c0;">&#9314;</span> makes use of the standard
105C&nbsp;library namespace <tt>ffi.C</tt>. Indexing this namespace with 111C&nbsp;library namespace <tt>ffi.C</tt>. Indexing this namespace with
106a symbol name (<tt>"printf"</tt>) automatically binds it to the the 112a symbol name (<tt>"printf"</tt>) automatically binds it to the the
107standard C&nbsp;library. The result is a special kind of object which, 113standard C&nbsp;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">
121local ffi = require("ffi") 127local ffi = require("ffi")
122ffi.cdef[[ 128ffi.cdef[[
123int 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]]
125ffi.C.MessageBoxA(nil, "Hello world!", "Test", 0) 131ffi.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
193bold: 199bold:
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;">&#9312;</span>
197ffi.cdef[[ 203<b>ffi.cdef[[
198typedef 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
201local function image_ramp_green(n) 207local 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;">&#9313;</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;">&#9314;</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;">&#9315;</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
209end 215end
210 216
211local function image_to_grey(img, n) 217local 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;">&#9314;</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;">&#9316;</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
216end 222end
@@ -222,25 +228,37 @@ for i=1,1000 do
222end 228end
223</pre> 229</pre>
224<p> 230<p>
225Ok, so that wasn't too difficult: first, load the FFI library and 231Ok, so that wasn't too difficult:
226declare the low-level data type. Here we choose a <tt>struct</tt> 232</p>
227which holds four byte fields, one for each component of a 4x8&nbsp;bit 233<p>
228RGBA pixel. 234<span style="color:#4040c0;">&#9312;</span> First, load the FFI
235library and declare the low-level data type. Here we choose a
236<tt>struct</tt> which holds four byte fields, one for each component
237of a 4x8&nbsp;bit RGBA pixel.
238</p>
239<p>
240<span style="color:#4040c0;">&#9313;</span> Creating the data
241structure with <tt>ffi.new()</tt> is straightforward &mdash; the
242<tt>'?'</tt> is a placeholder for the number of elements of a
243variable-length array.
244</p>
245<p>
246<span style="color:#4040c0;">&#9314;</span> C&nbsp;arrays are
247zero-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
249simplify converting legacy code.
229</p> 250</p>
230<p> 251<p>
231Creating the data structure with <tt>ffi.new()</tt> is straightforward 252<span style="color:#4040c0;">&#9315;</span> Since <tt>ffi.new()</tt>
232&mdash; the <tt>'?'</tt> is a placeholder for the number of elements 253zero-fills the array by default, we only need to set the green and the
233of a variable-length array. C&nbsp;arrays are zero-based, so the 254alpha fields.
234indexes have to run from <tt>0</tt> to <tt>n-1</tt> (one might
235allocate one more element instead to simplify converting legacy
236code). Since <tt>ffi.new()</tt> zero-fills the array by default, we
237only need to set the green and the alpha fields.
238</p> 255</p>
239<p> 256<p>
240The calls to <tt>math.floor()</tt> can be omitted here, because 257<span style="color:#4040c0;">&#9316;</span> The calls to
241floating-point numbers are already truncated towards zero when 258<tt>math.floor()</tt> can be omitted here, because floating-point
242converting them to an integer. This happens implicitly when the number 259numbers are already truncated towards zero when converting them to an
243is stored in the fields of each pixel. 260integer. This happens implicitly when the number is stored in the
261fields of each pixel.
244</p> 262</p>
245<p> 263<p>
246Now let's have a look at the impact of the changes: first, memory 264Now let's have a look at the impact of the changes: first, memory