FFI: Finish FFI docs.

This commit is contained in:
Mike Pall
2011-02-11 01:21:46 +01:00
parent a2f9f1f831
commit a5aade2fa9
15 changed files with 469 additions and 157 deletions

View File

@@ -33,8 +33,6 @@
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_int64.html">64 bit Integers</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
@@ -86,22 +84,30 @@ Please use the FFI sub-topics in the navigation bar to learn more.
It's really easy to call an external C&nbsp;library function:
</p>
<pre class="code">
<span style="color:#000080;">local ffi = require("ffi")</span>
ffi.cdef[[
<span style="color:#00a000;font-weight:bold;">int printf(const char *fmt, ...);</span>
local ffi = require("ffi") <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">&#9312;</span>
ffi.cdef[[ <span style="color:#f0f4ff;">//</span><span style="color:#4040c0;">&#9313;</span>
<span style="color:#00a000;">int printf(const char *fmt, ...);</span>
]]
<span style="color:#c06000;font-weight:bold;">ffi.C</span>.printf("Hello %s!", "world")
ffi.C.printf("Hello %s!", "world") <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">&#9314;</span>
</pre>
<p>
So, let's pick that apart: the first line (in blue) loads the FFI
library. The next one adds a C&nbsp;declaration for the function. The
part between the double-brackets (in green) is just standard
C&nbsp;syntax. And the last line calls the named C&nbsp;function. Yes,
it's that simple!
So, let's pick that apart:
</p>
<p>
<span style="color:#4040c0;">&#9312;</span> Load the FFI library.
</p>
<p>
<span style="color:#4040c0;">&#9313;</span> Add a C&nbsp;declaration
for the function. The part inside the double-brackets (in green) is
just standard C&nbsp;syntax.
</p>
<p>
<span style="color:#4040c0;">&#9314;</span> Call the named
C&nbsp;function &mdash; Yes, it's that simple!
</p>
<p style="font-size: 8pt;">
Actually, what goes on behind the scenes is far from simple: the first
part of the last line (in orange) makes use of the standard
Actually, what goes on behind the scenes is far from simple: <span
style="color:#4040c0;">&#9314;</span> makes use of the standard
C&nbsp;library namespace <tt>ffi.C</tt>. Indexing this namespace with
a symbol name (<tt>"printf"</tt>) automatically binds it to the the
standard 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:
<pre class="code">
local ffi = require("ffi")
ffi.cdef[[
int MessageBoxA(void *w, const char *txt, const char *cap, int type);
<span style="color:#00a000;">int MessageBoxA(void *w, const char *txt, const char *cap, int type);</span>
]]
ffi.C.MessageBoxA(nil, "Hello world!", "Test", 0)
</pre>
@@ -193,24 +199,24 @@ And here's the FFI version. The modified parts have been marked in
bold:
</p>
<pre class="code">
<b>local ffi = require("ffi")
ffi.cdef[[
typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel;
<b>local ffi = require("ffi")</b> <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">&#9312;</span>
<b>ffi.cdef[[
</b><span style="color:#00a000;">typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel;</span><b>
]]</b>
local function image_ramp_green(n)
<b>local img = ffi.new("rgba_pixel[?]", n)</b>
<b>local img = ffi.new("rgba_pixel[?]", n)</b> <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">&#9313;</span>
local f = 255/(n-1)
for i=<b>0,n-1</b> do
<b>img[i].green = i*f</b>
for i=<b>0,n-1</b> do <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">&#9314;</span>
<b>img[i].green = i*f</b> <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">&#9315;</span>
<b>img[i].alpha = 255</b>
end
return img
end
local function image_to_grey(img, n)
for i=<b>0,n-1</b> do
local y = <b>0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue</b>
for i=<b>0,n-1</b> do <span style="color:#f0f4ff;">--</span><span style="color:#4040c0;">&#9314;</span>
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>
img[i].red = y; img[i].green = y; img[i].blue = y
end
end
@@ -222,25 +228,37 @@ for i=1,1000 do
end
</pre>
<p>
Ok, so that wasn't too difficult: first, load the FFI library and
declare the low-level data type. Here we choose a <tt>struct</tt>
which holds four byte fields, one for each component of a 4x8&nbsp;bit
RGBA pixel.
Ok, so that wasn't too difficult:
</p>
<p>
Creating the data structure with <tt>ffi.new()</tt> is straightforward
&mdash; the <tt>'?'</tt> is a placeholder for the number of elements
of a variable-length array. C&nbsp;arrays are zero-based, so the
indexes have to run from <tt>0</tt> to <tt>n-1</tt> (one might
allocate one more element instead to simplify converting legacy
code). Since <tt>ffi.new()</tt> zero-fills the array by default, we
only need to set the green and the alpha fields.
<span style="color:#4040c0;">&#9312;</span> First, load the FFI
library and declare the low-level data type. Here we choose a
<tt>struct</tt> which holds four byte fields, one for each component
of a 4x8&nbsp;bit RGBA pixel.
</p>
<p>
The calls to <tt>math.floor()</tt> can be omitted here, because
floating-point numbers are already truncated towards zero when
converting them to an integer. This happens implicitly when the number
is stored in the fields of each pixel.
<span style="color:#4040c0;">&#9313;</span> Creating the data
structure with <tt>ffi.new()</tt> is straightforward &mdash; the
<tt>'?'</tt> is a placeholder for the number of elements of a
variable-length array.
</p>
<p>
<span style="color:#4040c0;">&#9314;</span> C&nbsp;arrays are
zero-based, so the indexes have to run from <tt>0</tt> to
<tt>n-1</tt>. One might want to allocate one more element instead to
simplify converting legacy code.
</p>
<p>
<span style="color:#4040c0;">&#9315;</span> Since <tt>ffi.new()</tt>
zero-fills the array by default, we only need to set the green and the
alpha fields.
</p>
<p>
<span style="color:#4040c0;">&#9316;</span> The calls to
<tt>math.floor()</tt> can be omitted here, because floating-point
numbers are already truncated towards zero when converting them to an
integer. This happens implicitly when the number is stored in the
fields of each pixel.
</p>
<p>
Now let's have a look at the impact of the changes: first, memory