There are obvious upsides to using LuaJIT: It's considerably faster than plain Lua — up to a hundred times faster — and it comes with a really nice way of loading shared libraries through its FFI library.
First, let's start off by creating a hybrid C and C++ shared library. That means you can either use a C or C++ compiler to build it.
Put the following in a file called
To compile it, pass
-fPIC to generate position independent code,
produce a shared library and set the output file to
`libfirst.dylib for OS X).
The C version of the program will be
Now that we've made
libfoo.so, we can inspect it.
We can list its symbols
If we remove the debugging symbols for
libfirst.so, we can't use
nm, but we
We also know the signature of the function
That's really all we need to load a shared library using LuaJIT. Let's try it out in the REPL first.
We not have to lef
ffi know input and output arguments for the function
add, by simply passing the function signature to
Now we can call
That's how easy it is. For Python users, there is the
cffi module that comes
pypy, which offers similar functionality (unlike
ctypes, which doesn't
parse C signatures automatically). Many other languages have it too. Chicken
Scheme also parses C code. The difference is in how advanced the C parsers are.
But why would you interface with C? I think it's very obvious. Most interesting platform specific functions will be available in C. Having a good FFI library means you can easily access these in LuaJIT. It's also easy to interface with libraries such as SDL.
The next step is to use C++ objects. There are many ways of doing this, so I'll
focus on one. We'll create a C++ class in a file
foo.cpp, then we'll expose
it through a C interface that we'll use from LuaJIT. Finally, we'll wrap this
interface back into an object-like one in LuaJIT.
The C interface will look like this:
Note that the
strdup function in
name is not guaranteed to exist on your
system. You can roll your own with something like
We need to tell LuaJIT's FFI library what the function signatures are.
We'll wrap this up in an object-like structure using a trick.
Notice that we pass the pointer to
ffi.gc, which makes sure to call
foo.delete_person on the pointer reclaiming it.
name function, we get a newly allocated string using
malloc, so we
need to use
C.free to remove it from the heap again. To load the C library,
We can now implement the wrappers for
Finally, let's try it out:
Running it produces