- Lua Quick Reference
- How To Reference Lua In Chemistry
- How To Reference Lua In Chicago
- Lua Reference Pdf
In this short tutorial I'll show how to run Lua programs from C and C++ and howto expose functions to them. It's easy!
Lua C API reference By now, you have probably noticed that working with the Lua stack can get a bit confusing. Some functions push and pop values onto the stack and others don't. Learn Lua quickly with this short yet comprehensive and friendly script. It's written as both an introduction and a quick reference. It's also a valid Lua script so you can verify that the code does what it says, and learn more by modifying and running this script in your Lua interpreter.
Update: The code in this post has been updated for Lua 5.2.4. I haven'tchecked if the Lua 5.3 C API is backwards-compatible with 5.2. All the codehere is available on GitHub.
The first program will just create a Lua state object and exit. It will be ahybrid between C and C++. Since the two languages must include different files,we need to discern between them by checking for the existence of the__cplusplus
macro.
Notice that I'm being explicit about which version of Lua I'm using in thecode. If you trust that the Lua developers care about compatibility, you canjust #include <lua.hpp>
and so on directly.
The purpose of the program is just to make sure that we can compile, link andrun it without errors.
You need to let the compiler know where it can find the include files and theLua shared library. The include files are usually located in/usr/local/include
and the library files in /usr/local/lib
. Search yoursystem directories if needed. To compile the above program, pass thedirectories with -I
and -L
, respectively.
You may swap out g++
with llvm-g++
, or just c++
, depending on yourcompiler. If you're using a C compiler, use gcc
or llvm-gcc
— butremember to rename the file to first.c
.
Now try to run the program to make sure it doesn't segfault:
This one worked just fine.
Executing Lua programs from a host
The next step is to execute Lua programs from your C or C++ code. We'll createthe Lua state object as above, load a file from disk and execute it.
Put this into runlua.cpp
or runlua.c
:
You can reuse the compilation arguments from above:
or
Running Lua programs
Let's test this with some Lua programs. The first one prints the Lua versionand exits.
You may want to double-check that it works by running lua hello.lua
. It maynot be important for this trivial program, but can become important when youtry more advanced ones.
Now try it with runlua
:
You can even run bytecode-compiled programs:
We should also check that the error handling works. Put some garbage in a filecalled error.lua
, for example
Running it produces
Calling C functions from Lua
It gets very interesting when Lua programs call back to your C or C++functions. We'll create a function called howdy
that prints its inputarguments and returns the integer 123.
To be on the safe side, we'll declare C linkage for the function in the C++version of the program. This has to do with name mangling,but in this case, it really doesn't matter: Lua just receives a pointer to afunction, and that's that. But if you start using dynamic loading of sharedlibraries through dlopen
and dlsym
, this will be an issue. So let's do itcorrect from the start.
Copy the above program into a file called callback.cpp
and add the howdy
function.
We have to pass the address of this function to Lua along with a name. Put thefollowing line somewhere between the call to lua_newstate
andluaL_loadfile
:
Create a test program called callback.lua
Compile and test it
I told you it was easy!
What next?
Read the Lua C APIReference. You've learned enough now to get going with it. Did you see mynote about clearing the stack in howdy
? You may want to investigate that.
Find out how to integrate Lua closures with your C functions.
If you want to hide or catch console output from Lua, you need to figure thatout as well. I once did it by trapping io.write()
; I copied its code fromlualib.c
and changed io_write
to point to my own function. There isprobably a better way to do it, though. Doing so is useful for things like gameprogramming.
Use RAIIor smart pointers to manage resources like lua_State
.
I also strongly recommend to try out LuaJIT.Calling into your functions there is even easier, using LuaJIT's foreignfunction library. I'll write a blog post on how todo that as well. In short, just create ordinary C functions, compile as ashared library, copy their signatures into pure Lua source code and hook themup with LuaJIT's FFIlibrary.
LuaJIT runs between 10-20 and up to 135 times faster than interpreted Lua, soit's definitely worth it.
The FFI library allows calling external C functions andusing C data structures from pure Lua code.
The FFI library largely obviates the need to write tedious manualLua/C bindings in C. No need to learn a separate binding language— it parses plain C declarations! These can becut-n-pasted from C header files or reference manuals. It's up tothe task of binding large libraries without the need for dealing withfragile binding generators.
The FFI library is tightly integrated into LuaJIT (it's not availableas a separate module). The code generated by the JIT-compiler foraccesses to C data structures from Lua code is on par with thecode a C compiler would generate. Calls to C functions canbe inlined in JIT-compiled code, unlike calls to functions bound viathe classic Lua/C API.
This page gives a short introduction to the usage of the FFI library.Please use the FFI sub-topics in the navigation bar to learn more.
Motivating Example: Calling External C Functions
Lua Quick Reference
It's really easy to call an external C library function:
So, let's pick that apart:
① Load the FFI library.
② Add a C declarationfor the function. The part inside the double-brackets (in green) isjust standard C syntax.
③ Call the namedC function — Yes, it's that simple!
Actually, what goes on behind the scenes is far from simple:
Ok, so maybe the use of printf() wasn't such a spectacularexample. You could have done that with io.write() andstring.format(), too. But you get the idea ...
So here's something to pop up a message box on Windows:
Bing! Again, that was far too easy, no?
Compare this with the effort required to bind that function using theclassic Lua/C API: create an extra C file, add a C functionthat retrieves and checks the argument types passed from Lua and callsthe actual C function, add a list of module functions and theirnames, add a luaopen_* function and register all modulefunctions, compile and link it into a shared library (DLL), move it tothe proper path, add Lua code that loads the module aaaand ... finallycall the binding function. Phew!
Motivating Example: Using C Data Structures
The FFI library allows you to create and access C datastructures. Of course the main use for this is for interfacing withC functions. But they can be used stand-alone, too.
Lua is built upon high-level data types. They are flexible, extensibleand dynamic. That's why we all love Lua so much. Alas, this can beinefficient for certain tasks, where you'd really want a low-leveldata type. E.g. a large array of a fixed structure needs to beimplemented with a big table holding lots of tiny tables. This imposesboth a substantial memory overhead as well as a performance overhead.
Here's a sketch of a library that operates on color images plus asimple benchmark. First, the plain Lua version:
This creates a table with 160.000 pixels, each of which is a tableholding four number values in the range of 0-255. First an image witha green ramp is created (1D for simplicity), then the image isconverted to greyscale 1000 times. Yes, that's silly, but I was inneed of a simple example ...
And here's the FFI version. The modified parts have been marked inbold:
Ok, so that wasn't too difficult:
How To Reference Lua In Chemistry
① First, load the FFIlibrary and declare the low-level data type. Here we choose astruct which holds four byte fields, one for each componentof a 4x8 bit RGBA pixel.
② Creating the datastructure with ffi.new() is straightforward — the'?' is a placeholder for the number of elements of avariable-length array.
③ C arrays arezero-based, so the indexes have to run from 0 ton-1. One might want to allocate one more element instead tosimplify converting legacy code.
④ Since ffi.new()zero-fills the array by default, we only need to set the green and thealpha fields.
⑤ The calls tomath.floor() can be omitted here, because floating-pointnumbers are already truncated towards zero when converting them to aninteger. This happens implicitly when the number is stored in thefields of each pixel.
Now let's have a look at the impact of the changes: first, memoryconsumption for the image is down from 22 Megabytes to640 Kilobytes (400*400*4 bytes). That's a factor of 35x less! So,yes, tables do have a noticeable overhead. BTW: The original programwould consume 40 Megabytes in plain Lua (on x64).
Next, performance: the pure Lua version runs in 9.57 seconds (52.9seconds with the Lua interpreter) and the FFI version runs in 0.48seconds on my machine (YMMV). That's a factor of 20x faster (110xfaster than the Lua interpreter).
The avid reader may notice that converting the pure Lua version overto use array indexes for the colors ([1] instead of.red, [2] instead of .green etc.) ought tobe more compact and faster. This is certainly true (by a factor of~1.7x). Switching to a struct-of-arrays would help, too.
How To Reference Lua In Chicago
However the resulting code would be less idiomatic and rathererror-prone. And it still doesn't get even close to the performance ofthe FFI version of the code. Also, high-level data structures cannotbe easily passed to other C functions, especially I/O functions,without undue conversion penalties.