1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
|
=pod
LuaJIT
=head1 FFI Tutorial
=over
=item * LuaJIT
=over
=item * Download E<rchevron>
=item * Installation
=item * Running
=back
=item * Extensions
=over
=item * FFI Library
=over
=item * FFI Tutorial
=item * ffi.* API
=item * FFI Semantics
=back
=item * jit.* Library
=item * Lua/C API
=item * Profiler
=back
=item * Status
=over
=item * Changes
=back
=item * FAQ
=item * Performance E<rchevron>
=item * Wiki E<rchevron>
=item * Mailing List E<rchevron>
=back
This page is intended to give you an overview of the features of the
FFI library by presenting a few use cases and guidelines.
This page makes no attempt to explain all of the FFI library, though.
You'll want to have a look at the ffi.* API function reference and the
FFI semantics to learn more.
=head2 Loading the FFI Library
The FFI library is built into LuaJIT by default, but it's not loaded
and initialized by default. The suggested way to use the FFI library is
to add the following to the start of every Lua file that needs one of
its functions:
local ffi = require("ffi")
Please note this doesn't define an C<ffi> variable in the table of
globals E<mdash> you really need to use the local variable. The
C<require> function ensures the library is only loaded once.
Note: If you want to experiment with the FFI from the interactive
prompt of the command line executable, omit the C<local>, as it doesn't
preserve local variables across lines.
=head2 Accessing Standard System Functions
The following code explains how to access standard system functions. We
slowly print two lines of dots by sleeping for 10 milliseconds after
each dot:
Â
â
â¡
â¢
â£
â¤
â¥local ffi = require("ffi")
ffi.cdef[[
void Sleep(int ms);
int poll(struct pollfd *fds, unsigned long nfds, int timeout);
]]
local sleep
if ffi.os == "Windows" then
function sleep(s)
ffi.C.Sleep(s*1000)
end
else
function sleep(s)
ffi.C.poll(nil, 0, s*1000)
end
end
for i=1,160 do
io.write("."); io.flush()
sleep(0.01)
end
io.write("\n")
Here's the step-by-step explanation:
This defines the C library functions we're going to use. The part
inside the double-brackets (in green) is just standard C syntax. You
can usually get this info from the C header files or the documentation
provided by each C library or C compiler.
The difficulty we're facing here, is that there are different standards
to choose from. Windows has a simple C<Sleep()> function. On other
systems there are a variety of functions available to achieve
sub-second sleeps, but with no clear consensus. Thankfully C<poll()>
can be used for this task, too, and it's present on most non-Windows
systems. The check for C<ffi.os> makes sure we use the Windows-specific
function only on Windows systems.
Here we're wrapping the call to the C function in a Lua function. This
isn't strictly necessary, but it's helpful to deal with system-specific
issues only in one part of the code. The way we're wrapping it ensures
the check for the OS is only done during initialization and not for
every call.
A more subtle point is that we defined our C<sleep()> function (for the
sake of this example) as taking the number of seconds, but accepting
fractional seconds. Multiplying this by 1000 gets us milliseconds, but
that still leaves it a Lua number, which is a floating-point value.
Alas, the C<Sleep()> function only accepts an integer value. Luckily
for us, the FFI library automatically performs the conversion when
calling the function (truncating the FP value towards zero, like in C).
Some readers will notice that C<Sleep()> is part of C<KERNEL32.DLL> and
is also a C<stdcall> function. So how can this possibly work? The FFI
library provides the C<ffi.C> default C library namespace, which allows
calling functions from the default set of libraries, like a C compiler
would. Also, the FFI library automatically detects C<stdcall>
functions, so you don't need to declare them as such.
The C<poll()> function takes a couple more arguments we're not going to
use. You can simply use C<nil> to pass a C<NULL> pointer and C<0> for
the C<nfds> parameter. Please note that the number C<0> I<does not
convert to a pointer value>, unlike in C++. You really have to pass
pointers to pointer arguments and numbers to number arguments.
The page on FFI semantics has all of the gory details about conversions
between Lua objects and C types. For the most part you don't have to
deal with this, as it's performed automatically and it's carefully
designed to bridge the semantic differences between Lua and C.
Now that we have defined our own C<sleep()> function, we can just call
it from plain Lua code. That wasn't so bad, huh? Turning these boring
animated dots into a fascinating best-selling game is left as an
exercise for the reader. :-)
=head2 Accessing the zlib Compression Library
The following code shows how to access the zlib compression library
from Lua code. We'll define two convenience wrapper functions that take
a string and compress or uncompress it to another string:
Â
â
â¡
â¢
â£
â¤
â¥
â¦local ffi = require("ffi")
ffi.cdef[[
unsigned long compressBound(unsigned long sourceLen);
int compress2(uint8_t *dest, unsigned long *destLen,
const uint8_t *source, unsigned long sourceLen, int level);
int uncompress(uint8_t *dest, unsigned long *destLen,
const uint8_t *source, unsigned long sourceLen);
]]
local zlib = ffi.load(ffi.os == "Windows" and "zlib1" or "z")
local function compress(txt)
local n = zlib.compressBound(#txt)
local buf = ffi.new("uint8_t[?]", n)
local buflen = ffi.new("unsigned long[1]", n)
local res = zlib.compress2(buf, buflen, txt, #txt, 9)
assert(res == 0)
return ffi.string(buf, buflen[0])
end
local function uncompress(comp, n)
local buf = ffi.new("uint8_t[?]", n)
local buflen = ffi.new("unsigned long[1]", n)
local res = zlib.uncompress(buf, buflen, comp, #comp)
assert(res == 0)
return ffi.string(buf, buflen[0])
end
-- Simple test code.
local txt = string.rep("abcd", 1000)
print("Uncompressed size: ", #txt)
local c = compress(txt)
print("Compressed size: ", #c)
local txt2 = uncompress(c, #txt)
assert(txt2 == txt)
Here's the step-by-step explanation:
This defines some of the C functions provided by zlib. For the sake of
this example, some type indirections have been reduced and it uses the
pre-defined fixed-size integer types, while still adhering to the zlib
API/ABI.
This loads the zlib shared library. On POSIX systems it's named
C<libz.so> and usually comes pre-installed. Since C<ffi.load()>
automatically adds any missing standard prefixes/suffixes, we can
simply load the C<"z"> library. On Windows it's named C<zlib1.dll> and
you'll have to download it first from the E<rchevron> zlib site. The
check for C<ffi.os> makes sure we pass the right name to C<ffi.load()>.
First, the maximum size of the compression buffer is obtained by
calling the C<zlib.compressBound> function with the length of the
uncompressed string. The next line allocates a byte buffer of this
size. The C<[?]> in the type specification indicates a variable-length
array (VLA). The actual number of elements of this array is given as
the 2nd argument to C<ffi.new()>.
This may look strange at first, but have a look at the declaration of
the C<compress2> function from zlib: the destination length is defined
as a pointer! This is because you pass in the maximum buffer size and
get back the actual length that was used.
In C you'd pass in the address of a local variable (C<&buflen>). But
since there's no address-of operator in Lua, we'll just pass in a
one-element array. Conveniently it can be initialized with the maximum
buffer size in one step. Calling the actual C<zlib.compress2> function
is then straightforward.
We want to return the compressed data as a Lua string, so we'll use
C<ffi.string()>. It needs a pointer to the start of the data and the
actual length. The length has been returned in the C<buflen> array, so
we'll just get it from there.
Note that since the function returns now, the C<buf> and C<buflen>
variables will eventually be garbage collected. This is fine, because
C<ffi.string()> has copied the contents to a newly created (interned)
Lua string. If you plan to call this function lots of times, consider
reusing the buffers and/or handing back the results in buffers instead
of strings. This will reduce the overhead for garbage collection and
string interning.
The C<uncompress> functions does the exact opposite of the C<compress>
function. The compressed data doesn't include the size of the original
string, so this needs to be passed in. Otherwise no surprises here.
The code, that makes use of the functions we just defined, is just
plain Lua code. It doesn't need to know anything about the LuaJIT FFI
E<mdash> the convenience wrapper functions completely hide it.
One major advantage of the LuaJIT FFI is that you are now able to write
those wrappers I<in Lua>. And at a fraction of the time it would cost
you to create an extra C module using the Lua/C API. Many of the
simpler C functions can probably be used directly from your Lua code,
without any wrappers.
Side note: the zlib API uses the C<long> type for passing lengths and
sizes around. But all those zlib functions actually only deal with 32
bit values. This is an unfortunate choice for a public API, but may be
explained by zlib's history E<mdash> we'll just have to deal with it.
First, you should know that a C<long> is a 64 bit type e.g. on
POSIX/x64 systems, but a 32 bit type on Windows/x64 and on 32 bit
systems. Thus a C<long> result can be either a plain Lua number or a
boxed 64 bit integer cdata object, depending on the target system.
Ok, so the C<ffi.*> functions generally accept cdata objects wherever
you'd want to use a number. That's why we get a away with passing C<n>
to C<ffi.string()> above. But other Lua library functions or modules
don't know how to deal with this. So for maximum portability one needs
to use C<tonumber()> on returned C<long> results before passing them
on. Otherwise the application might work on some systems, but would
fail in a POSIX/x64 environment.
=head2 Defining Metamethods for a C Type
The following code explains how to define metamethods for a C type. We
define a simple point type and add some operations to it:
Â
â
â¡
â¢
â£
â¤
â¥local ffi = require("ffi")
ffi.cdef[[
typedef struct { double x, y; } point_t;
]]
local point
local mt = {
__add = function(a, b) return point(a.x+b.x, a.y+b.y) end,
__len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end,
__index = {
area = function(a) return a.x*a.x + a.y*a.y end,
},
}
point = ffi.metatype("point_t", mt)
local a = point(3, 4)
print(a.x, a.y) --> 3 4
print(#a) --> 5
print(a:area()) --> 25
local b = a + point(0.5, 8)
print(#b) --> 12.5
Here's the step-by-step explanation:
This defines the C type for a two-dimensional point object.
We have to declare the variable holding the point constructor first,
because it's used inside of a metamethod.
Let's define an C<__add> metamethod which adds the coordinates of two
points and creates a new point object. For simplicity, this function
assumes that both arguments are points. But it could be any mix of
objects, if at least one operand is of the required type (e.g. adding a
point plus a number or vice versa). Our C<__len> metamethod returns the
distance of a point to the origin.
If we run out of operators, we can define named methods, too. Here the
C<__index> table defines an C<area> function. For custom indexing
needs, one might want to define C<__index> and C<__newindex>
I<functions> instead.
This associates the metamethods with our C type. This only needs to be
done once. For convenience, a constructor is returned by
C<ffi.metatype()>. We're not required to use it, though. The original C
type can still be used e.g. to create an array of points. The
metamethods automatically apply to any and all uses of this type.
Please note that the association with a metatable is permanent and
B<the metatable must not be modified afterwards!> Ditto for the
C<__index> table.
Here are some simple usage examples for the point type and their
expected results. The pre-defined operations (such as C<a.x>) can be
freely mixed with the newly defined metamethods. Note that C<area> is a
method and must be called with the Lua syntax for methods: C<a:area()>,
not C<a.area()>.
The C type metamethod mechanism is most useful when used in conjunction
with C libraries that are written in an object-oriented style. Creators
return a pointer to a new instance and methods take an instance pointer
as the first argument. Sometimes you can just point C<__index> to the
library namespace and C<__gc> to the destructor and you're done. But
often enough you'll want to add convenience wrappers, e.g. to return
actual Lua strings or when returning multiple values.
Some C libraries only declare instance pointers as an opaque C<void *>
type. In this case you can use a fake type for all declarations, e.g. a
pointer to a named (incomplete) struct will do: C<typedef struct
foo_type *foo_handle>. The C side doesn't know what you declare with
the LuaJIT FFI, but as long as the underlying types are compatible,
everything still works.
=head2 Translating C Idioms
Here's a list of common C idioms and their translation to the LuaJIT
FFI:
Idiom
C code
Lua code
Pointer dereference
C<int *p;>
x = *p;
*p = y;
x = B<p[0]>
B<p[0]> = y
Pointer indexing
C<int i, *p;>
x = p[i];
p[i+1] = y;
x = p[i]
p[i+1] = y
Array indexing
C<int i, a[];>
x = a[i];
a[i+1] = y;
x = a[i]
a[i+1] = y
C<struct>/C<union> dereference
C<struct foo s;>
x = s.field;
s.field = y;
x = s.field
s.field = y
C<struct>/C<union> pointer deref.
C<struct foo *sp;>
x = sp-E<gt>field;
sp-E<gt>field = y;
x = B<s.field>
B<s.field> = y
Pointer arithmetic
C<int i, *p;>
x = p + i;
y = p - i;
x = p + i
y = p - i
Pointer difference
C<int *p1, *p2;>
C<x = p1 - p2;>
C<x = p1 - p2>
Array element pointer
C<int i, a[];>
C<x = &a[i];>
C<x = B<a+i>>
Cast pointer to address
C<int *p;>
C<x = (intptr_t)p;>
x = tonumber(
ffi.cast("intptr_t",
p))
Functions with outargs
C<void foo(int *inoutlen);>
int len = x;
foo(&len);
y = len;
local len =
ffi.new("int[1]", x)
foo(len)
y = len[0]
Vararg conversions
C<int printf(char *fmt, ...);>
printf("%g", 1.0);
printf("%d", 1);
printf("%g", 1);
printf("%d",
B<ffi.new("int", 1)>)
=head2 To Cache or Not to Cache
It's a common Lua idiom to cache library functions in local variables
or upvalues, e.g.:
local byte, char = string.byte, string.char
local function foo(x)
return char(byte(x)+1)
end
This replaces several hash-table lookups with a (faster) direct use of
a local or an upvalue. This is less important with LuaJIT, since the
JIT compiler optimizes hash-table lookups a lot and is even able to
hoist most of them out of the inner loops. It can't eliminate I<all> of
them, though, and it saves some typing for often-used functions. So
there's still a place for this, even with LuaJIT.
The situation is a bit different with C function calls via the FFI
library. The JIT compiler has special logic to eliminate I<all of the
lookup overhead> for functions resolved from a C library namespace!
Thus it's not helpful and actually counter-productive to cache
individual C functions like this:
local funca, funcb = ffi.C.funca, ffi.C.funcb -- Not helpful!
local function foo(x, n)
for i=1,n do funcb(funca(x, i), 1) end
end
This turns them into indirect calls and generates bigger and slower
machine code. Instead you'll want to cache the namespace itself and
rely on the JIT compiler to eliminate the lookups:
local C = ffi.C -- Instead use this!
local function foo(x, n)
for i=1,n do C.funcb(C.funca(x, i), 1) end
end
This generates both shorter and faster code. So B<don't cache C
functions>, but B<do> cache namespaces! Most often the namespace is
already in a local variable at an outer scope, e.g. from C<local lib =
ffi.load(...)>. Note that copying it to a local variable in the
function scope is unnecessary.
----
Copyright E<copy> 2005-2017 Mike Pall E<middot> Contact
=cut
#Pod::HTML2Pod conversion notes:
#From file ext_ffi_tutorial.html
# 22557 bytes of input
#Mon May 14 13:19:16 2018 agentzh
# No a_name switch not specified, so will not try to render <a name='...'>
# No a_href switch not specified, so will not try to render <a href='...'>
# Deleting phrasal "code" element (`tt_100) because it has super-phrasal elements (`br_33, `br_34) as children.
# Deleting phrasal "code" element (`tt_99) because it has super-phrasal elements (`br_31, `br_32) as children.
# Deleting phrasal "b" element (`b_8) because it has super-phrasal elements (`br_27, `br_28, `br_29) as children.
# Deleting phrasal "code" element (`tt_97) because it has super-phrasal elements (`br_27, `br_28, `br_29) as children.
# Deleting phrasal "code" element (`tt_96) because it has super-phrasal elements (`br_25, `br_26) as children.
# Deleting phrasal "b" element (`b_7) because it has super-phrasal elements (`br_22, `br_23) as children.
# Deleting phrasal "code" element (`tt_94) because it has super-phrasal elements (`br_22, `br_23) as children.
# Deleting phrasal "code" element (`tt_85) because it has super-phrasal elements (`br_18) as children.
# Deleting phrasal "code" element (`tt_84) because it has super-phrasal elements (`br_17) as children.
# Deleting phrasal "code" element (`tt_82) because it has super-phrasal elements (`br_15) as children.
# Deleting phrasal "code" element (`tt_81) because it has super-phrasal elements (`br_14) as children.
# Deleting phrasal "code" element (`tt_77) because it has super-phrasal elements (`br_12) as children.
# Deleting phrasal "code" element (`tt_76) because it has super-phrasal elements (`br_11) as children.
# Deleting phrasal "code" element (`tt_72) because it has super-phrasal elements (`br_9) as children.
# Deleting phrasal "code" element (`tt_71) because it has super-phrasal elements (`br_8) as children.
# Deleting phrasal "code" element (`tt_69) because it has super-phrasal elements (`br_6) as children.
# Deleting phrasal "code" element (`tt_68) because it has super-phrasal elements (`br_5) as children.
# Deleting phrasal "code" element (`tt_66) because it has super-phrasal elements (`br_3) as children.
# Deleting phrasal "code" element (`tt_65) because it has super-phrasal elements (`br_2) as children.
|