Call C Function In Lua

Passing Tables to Lua Functions; Introduction From a running C program, you can call a Lua script. The C program can pass arguments to the Lua script, and the Lua script can pass back a return. The Lua script can serve to initialize the C program, or the Lua script can install a callback routine in the C program. Here the script basically is a function that takes two numbers and returns the sum of the two. Using the luagetglobal (L, 'sum') call, we load the function into the stack. We can check if the function was loaded correctly using the luaisfunction (L, -1). Then we pass the two arguments of the function by pushing them into the stack.

  1. Call C Function In Java
  2. Lua Register C Function
  3. Lua And C
  4. Lua Pcall Return

This first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences.
The fourth edition targets Lua 5.3 and is available at Amazon and other bookstores.
By buying the book, you also help to support the Lua project.

Programming in Lua
Part IV. The C APIChapter 26. Calling C from Lua

One of the basic means for extending Luais for the application to registernew C functions into Lua.

Cpp

When we say that Lua can call C functions,this does not mean that Lua can call any C function.(There are packages that allow Lua to call any C function,but they are neither portable nor robust.)As we saw previously,when C calls a Lua function,it must follow a simple protocol to pass the arguments andto get the results.Similarly,for a C function to be called from Lua,it must follow a protocolto get its arguments and to return its results.Moreover, for a C function to be called from Lua,we must register it, that is,we must give its address to Lua in an appropriate way.

When Lua calls a C function,it uses the same kind of stack that C uses to call Lua.The C function gets its arguments from the stackand pushes the results on the stack.To distinguish the results from other values on the stack,the function returns (in C) the number of results itis leaving on the stack.An important concept here is that the stack is not a global structure;each function has its own private local stack.When Lua calls a C function,the first argument will always be at index 1 of this local stack.Even when a C function calls Lua code that calls thesame (or another) C function again,each of these invocations sees only its own private stack,with its first argument at index 1.

Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved.

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

It's really easy to call an external C library function:

Call C Function In Lua

So, let's pick that apart:

Load the FFI library.

Call C Function In Java

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: ③ makes use of the standardC library namespace ffi.C. Indexing this namespace witha symbol name ('printf') automatically binds it to thestandard C library. The result is a special kind of object which,when called, runs the printf function. The arguments passedto this function are automatically converted from Lua objects to thecorresponding C types.

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?

Lua Register C Function

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.

Call C Function In Lua

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:

Lua And C

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.

Lua Pcall Return

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.