FFI C declaration composer

This example illustrates how to generate foreign function interface (FFI) bindings for a C library using the Lua plugin for GCC and the ffi-cdecl module. The C API of the library is extracted using a C source file that contains capture macros, and matching FFI C bindings are generated using the C declaration composer for GCC.

After following the installation instructions, you may run the example:

make -C ffi-cdecl

If the GCC plugin is not installed in the GCC plugin directory:

make -C ffi-cdecl GCCLUA=$HOME/projects/gcc-lua/gcc/gcclua.so

The FFI C bindings are written to the file C.lua:

local ffi = require("ffi")

ffi.cdef[[
int getopt(int, char *const *, const char *);
extern char *optarg;
typedef int clockid_t;
struct timespec {
  long int tv_sec;
  long int tv_nsec;
};
static const int RLIM_INFINITY = -1;
]]

1 Usage

To generate FFI C bindings for a library, we compose a Lua script for the GCC C compiler:

First, we define a function that captures C declarations in a table:

Second, we output FFI C bindings for the captured declarations to a Lua file:

The script is executed by loading the Lua plugin for GCC as follows:

gcc -S C.c -fplugin=gcclua -fplugin-arg-gcclua-script=C.lua.in -fplugin-arg-gcclua-output=C.lua

If the GCC plugin is not installed in the GCC plugin directory:

gcc -S C.c -fplugin=$HOME/projects/gcc-lua/gcc/gcclua.so -fplugin-arg-gcclua-script=C.lua.in -fplugin-arg-gcclua-output=C.lua

2 C capture files

For the purpose of capturing the C API of a library, the C header ffi-cdecl.h defines a range of capture macros. These macros are used in a C source file that includes the header(s) of the library. Each capture macro receives an identifier that refers to a C declaration or preprocessor constant.

Consider the following capture file C.c for the POSIX C API:

The identifier in the generated FFI C binding may be overridden using the preprocessor:

3 C capture macros

The C header ffi-cdecl.h defines the following capture macros:

cdecl_type(id)

Captures the type declaration with the given identifier.

cdecl_memb(id)

Captures the type definition of a struct, union or enum type with the given identifier.

cdecl_struct(tag)

Captures the type definition of a struct type with the given tag.

cdecl_union(tag)

Captures the type definition of a union type with the given tag.

cdecl_enum(tag)

Captures the type definition of an enumeration type with the given tag.

cdecl_func(id)

Captures the function declaration with the given identifier.

Any subexpression containing an address-of, cast, or comma operator is replaced by its right-most operand.

cdecl_var(id)

Captures the variable declaration with the given identifier.

Any subexpression containing an address-of, cast, or comma operator is replaced by its right-most operand.

cdecl_const(id)

Captures the integer constant with the given identifier.

Any subexpression containing an address-of, cast, or comma operator is replaced by its right-most operand.