I've just pushed a commit to LuaJIT git HEAD which always boxes enums. Accesses to enums inside a struct/union/array or enums returned from a called C function are boxed inside a newly created enum cdata object. Note that allocations for temporary boxes can usually be eliminated by the JIT compiler. Previously the returned enum was immediately converted to a number and its ctype was lost. Example: ffi.cdef[[ enum Foo { AAA = 1, BBB = 2 }; struct Bar { int i; enum Foo e; double d; } enum Foo myfunc(int); void myfunc_enumarg(enum Foo); ]] bar = ffi.new("struct Bar") ... print(bar.i) -- Returns plain Lua number print(bar.d) -- Returns plain Lua number print(bar.e) -- Returns boxed enum cdata object (NEW) print(mylib.myfunc(42)) -- Returns boxed enum cdata object (NEW) The returned enum cdata object behaves like an integer wrt. the FFI and converts readily back and forth to numbers. So you can e.g. pass such an enum object to an integer argument or store it to a double field and so on: bar.i = bar.e -- Implicit conversion from enum bar.d = bar.e -- Implicit conversion from enum bar.e = bar.i -- Implicit conversion to enum mylib.myfunc(bar.e) -- Implicit conversion from enum mylib.myfunc_enumarg(42) -- Implicit conversion to enum This change may break compatibility with existing programs using the FFI, if you pass an enum to a non-FFI function. Hopefully this is not very common. You may need to explicitly convert the enum to a plain Lua number with tonumber(). Or better declare the field or return value as an integer, if it's usually treated like a number. A new feature is that comparisons and arithmetic operations automatically convert a string operand that matches an enum constant to its value, provided the other operand is an enum. This is the same implicit conversion that's used for storing to enum fields/elements or passing enum arguments (already worked before): bar.e = "AAA" -- Same as bar.e = 1 mylib.myfunc("AAA") -- Same as mylib.myfunc(1) if bar.e == "BBB" then ... end -- Same as bar.e == 2 (NEW) if mylib.myfunc(42) == "BBB" then ... end -- Same as mylib.myfunc(42) == 2 (NEW) Here's an example from the expat API: ffi.cdef[[ enum XML_Status { XML_STATUS_ERROR = 0, XML_STATUS_OK = 1, XML_STATUS_SUSPENDED = 2 }; // ... Needs more declarations ... enum XML_Status XML_StopParser(XML_Parser parser, uint8_t resumable); ]] if lib.XML_StopParser(parser, 1) ~= "XML_STATUS_OK" then ... end You couldn't do this before, because the enum type was lost with the implicit conversion to a number (and a number never compares equal to a string). --Mike