Currently, the FFI supports most features one would expect it to support, notably:
- Near complete C11 declarations syntax, plus the following extensions:
- Unnamed parameters
- Opaque
enumdeclarations - Transparent
structinsidestructorunion __const__,__volatile__- C++ references
__alignof__- Zero sized arrays, structs and unions
__asm__("symbol")(redirection)__cdecl,__fastcall,__stdcall,__thiscall__attribute__with:cdecl,fastcall,stdcall,thiscall- Empty argument list is treated like C++, i.e.
void foo();has no args
- All API supported by LuaJIT FFI, plus the following extensions:
cffi.addressof(like C++&:TorT &becomesT *)cffi.toretval(cdata -> Lua return value conversion)cffi.eval(constant expression -> cdata)cffi.nullptr(aNULLpointer constant for comparisons)cffi.tonumber(cdata-awaretonumber)cffi.type(cdata-awaretype)
- Semantics generally follow LuaJIT closely, with these exceptions:
- All metamethods of the respective Lua version are respected
- Lua integers are supported (and used) when using Lua 5.3 or newer
- Windows
__stdcallfunctions must be explicitly marked as such - Equality comparisons of
cdataandnildo not work (usecffi.nullptr)- This is a limitation of the Lua metamethod semantics
- You can reassign the values of fields of a
metatype- Which fields are used is decided at
cffi.metatypecall time, though
- Which fields are used is decided at
cffi.gccan be used with anycdata- Callbacks are currently unrestricted (no limit, no handle reuse)
- This may change in the future, so do not rely on it
Since libffi does not have reliable support for unions, cffi does not
support it for all targets, only those that are explicitly handled. Currently
this includes:
- 32-bit x86 (all)
- 64-bit x86 (Windows)
- 32-bit ARM (all)
- 32-bit PowerPC
- MIPS(64) (all)
Every other target forbids this. Both passing and returning is forbidden, and structs containing unions are likewise not allowed. Keep in mind that this only applies to parameter passing and returning by value; you can pass them by pointer everywhere, as well as allocate them.
The system will not let you declare such functions on unsupported targets.
The cffi.abi("unionval") can be used to check the support from Lua in a generic
manner.
There are some things notably missing at this point.
- Syntax:
- Transparent
enuminsidestruct(non-standard extension) static constdeclarations insidestruct/union(C++ extension)
- Transparent
- Bitfields (
libffilimitation) - Complex types (
complex,_Complex,complex double,complex float) alignas(and_Alignas)- Vector types (GCC extension)
__attribute__withpacked,vector_size,aligned,mode(GCC extension)__extension__(GCC extension)__declspec(align(n))(MSVC extension)__ptr32,__ptr64(MSVC extension)#pragma pack(MSVC extension)- Passing
unionby value is not supported everywhere __stdcallon Windows is not auto-guessed and must be tagged explicitly
- Non-integer support in constant expressions
- Builtin C preprocessor
- Type system cleanup/rework
- Performance optimizations
- Resource usage optimizations
The project supports every system and architecture that has a libffi
implementation and a C++14 compiler. We have a continuous integration
setup that tests multiple architectures on Linux as well as x86_64
macOS and Windows.
In addition to supporting every Lua version starting with 5.1, effort is made when it comes to supporting unusual Lua configurations (such as ones with differently configured numeric types). This is however not tested, so if you run into issues, feel free to provide a patch.
The CI matrix currently includes the following:
| Architecture | Word size | Endianness | OS | Compiler | Build type |
|---|---|---|---|---|---|
x86_64 |
64 | little | Linux | gcc |
debugoptimized |
x86_64 |
64 | little | Linux | gcc |
release |
x86_64 |
64 | little | Linux | clang |
debugoptimized |
x86_64 |
64 | little | Windows | gcc |
release |
x86_64 |
64 | little | Windows | cl.exe |
debugoptimized |
x86_64 |
64 | little | MacOS | clang |
debugoptimized |
ppc64le |
64 | little | Linux | gcc |
debugoptimized |
ppc64 |
64 | big | Linux | gcc |
debugoptimized |
aarch64 |
64 | little | Linux | gcc |
debugoptimized |
riscv64 |
64 | little | Linux | gcc |
debugoptimized |
s390x |
64 | big | Linux | gcc |
debugoptimized |
i686 |
32 | little | Linux | gcc |
debugoptimized |
mips |
32 | big | Linux | gcc |
debugoptimized |
ppc |
32 | big | Linux | gcc |
debugoptimized |
armv6l |
32 | little | Linux | gcc |
debugoptimized |
Note: ppc64 is ABIv1.
Clang CI builds on x86_64 Linux also build with sanitizers (ASan, UBSan, CFI).
This is not an exhaustive list of supported targets but rather just a limited list intended to cover everything (64-bit systems, 32-bit systems, little and big endian, Linux, macOS and Windows, and release build to catch assertion related bugs).