Playing with LuaJIT FFI

What is LuaJIT?

Lua was for long time one of the fastest programming languages, and perhaps sounds new to you but it appeared on 1993, it is actually older than PHP! Then, LuaJIT emerged on 2005, quickly earning the title of “The fastest Lua interpreter”, and I think it can make V8 look like a turtle!

What is FFI?

One of the greatest features I love of LuaJIT is its FFI, which can speed up even more the performance. Do you remember the DLL Calls? the idea is to make direct calls to functions inside libraries, because certainly there are heavy tasks that C can handle better, and there are plenty of libraries over there. Now you don't need to code bindings all the time, with LuaJIT you just load the library and it does the magic for you! Another advantage of FFI is the reuse of a wide variety of C libraries, being the most used programming languages, most of them are pretty mature and are spread over major platforms (some are cross-platform).

Example 1

Enough talk about how great is FFI, now it is time to code something. My first try was with libcurl, here is the original C code:

#include <stdio.h>
#include <curl/curl.h>
int main(void)
  CURL *curl;
  CURLcode res;
  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "");
    res = curl_easy_perform(curl);
    /* always cleanup */
  return 0;

The previous example does a fetch of and exists. Pretty easy.

Now let's do the same with LuaJIT's FFI:

local ffi = require [[ffi]]

void *curl_easy_init();
int curl_easy_setopt(void *curl, char option, ...);
int curl_easy_perform(void *curl);
void curl_easy_cleanup(void *curl);
local libcurl = ffi.load("")
local CURLOPT_URL = 10002

local curl = libcurl.curl_easy_init()

if curl then
  libcurl.curl_easy_setopt(curl, CURLOPT_URL, "")
  res = libcurl.curl_easy_perform(curl)


There are some drawbacks, like the need of declaring the functions that are going to be used from the loaded C library. But the only drawback I care about is doing callbacks from C to Lua functions. By now possible but impractical, hopefully it is in the TODO list of the author.

NOTE: I do PHP code most of my day, but I'm seriously thinking on how great it would be to use C libraries directly instead of re-implementing in PHP code or writing plug-ins, perhaps my programs would have better performance and less code. In the other hand, Lua is not as mature as PHP for the web, so there is a long way till we see serious stuff that can compete with PHP. There are few uses cases that can benefit from FFI, but it does not means that has a lot of potential on the fields of performance tuning and code reuse.

Example 2

Let's give it another try. This time we are implementing output buffering using standard C functions:

local ffi = require [[ffi]]

ffi.cdef [[
typedef struct __IO_FILE FILE;
FILE *stdout;
int printf(const char *fmt, ...);
void setbuf(FILE *stream, char *buf);
void *malloc(size_t size);
void *memset(void *s, int c, size_t n);

local buffer = ffi.C.malloc(1024)

ffi.C.setbuf(ffi.C.stdout, buffer)

ffi.C.memset(buffer, 0, 1024)

local buffer = ffi.C.malloc(1024)
ffi.C.setbuf(ffi.C.stdout, buffer)
ffi.C.printf([[ World!



The code is pretty eloquent, a classic example of “Hello World!” is now used to split the text into an output buffer and the standard output.


LuJIT's FFI is an option one has to consider. There are some drawbacks like mentioned before, but there are solid points as well. Just make sure to remember that you will need to spend some time playing with FFI and getting familiar with the C library you are working with. Must confess that felt very frustrated at some point, when there were some “Segmentation fault” errors, memory leaks and other unexpected behaviors. If you are not used to code with C, then it is better to ask for support from an expert.


QR Code
QR Code playing_with_luajit_ffi (generated for current page)