Useful for LuaJIT FFI cdefs just straight up using the .h files
Used for generating the code in my Lua FFI bindings repo.
Depends on:
- C preproc lib for C preprocessing
- C H parser lib for C header parsing
Produces content for my
To generate all binding files for your current OS:
./make.lua all
To generate all starting at a specific point in the include list:
./make.lua 'start=<jpeglib.h>'
To generate all stopping at a specific point in the include list:
./make.lua 'stop=<jpeglib.h>'
To generate a single binding file:
./make.lua '<jpeglib.h>'
It then calls into generate.lua to produce the LuaJIT binding file.
The results are stored in results/ffi/*.
This file returns a single function generate(inc) that acts on an entry in the include-list.lua file.
It generates the LuaJIT binding file by talking to the system compiler (cl.exe or gcc),
environment macros, C preprocessor,
and C header parser.
The C preprocessor will generate parsed headers are specific to LuaJIT:
- They have
#defineconstants replaced withenum{}'s. - They have function prototypes preserved.
This contains a list of information on converting C to Lua files. It is used for the generation of the Lua binding files. Include list entries contain the following properties:
inc= the main.hinclude file , and what themake.luaCLI uses to identify what you are trying to generate. Should be wrapped in""or<>for user vs system search paths.out= the.luafile generated.os= whichffi.osthis file is specific to.moreincs= A list of any extra.hfiles that should be included in the Lua binding file generation.skipincs= A list of.hfiles that the preprocessor should skip over when it encounters an#includedirective.silentincs= A list of.hfiles that should be parsed for the sake of the preprocessor's state, but whose contents should be suppressed from the final Lua binding file.includedirs= A list of paths to add to our preprocessor include dir search path.macros= A list of entries to initially add to our preprocessor's macros.pkgconfig= The name of thepkg-config ${name} --cflagsscript to invoke.-Dflags are collected intoinc.macrosand-Iflags are collected intoinc.includedirs.final(code, preproc)= A final callback on the preprocessor-generated code in case the results need any hand-tuning.forcecode= For a rare few files, it's not worth parsing at all. Set this to just override the whole thing.dontGen= For Linux system include files. Some of the hoops I have to go through to get around generating the Lua equivalents of the Linux system files that are loaded up with preprocessors that error and say "never include this file directly!"...enumGenUnderscoreMacros= Used with a small few Linux system include files, I forget exactly why I used this but it was for preventing unnecessary enum output.ffiload= Planning on eventually using this for inserting entries intoffi/load.lua.macroincs= List of.h's, in addition toincandmoreincsthat the preprocessor should save#definenumeric values to convert into enums.
Fair warning, the OS-specific include files in there are pretty terse, but the 3rd party library include generation code is near the bottom and it is all very straightforward.
Some of the include-list.lua entries make use of the makeLibWrapper() function.
This will produce a moreso organize LuaJIT binding code that is designed to defer loading symbols until they are used.
These files will look like the following:
local ffi = require 'ffi'
-- comments
--[[
# comments and indecypherable macros go here
--]]
-- typedefs
-- C #include to Lua require() calls co here.
require 'ffi.req' 'c.stdio'
require 'ffi.req' 'c.stdlib'
require 'ffi.req' 'c.etc'
...
ffi.cdef[[
// C typedefs, named structs, and named enums go here.
...
]]
local wrapper
wrapper = require 'ffi.libwrapper'{
defs = {
-- enums
-- unnamed enum key/values go here, to be loaded upon their first reference.
...
-- functions
-- symbols (functions and extern-variables) go here, to be loaded upon their first reference.
...
},
}
-- macros
...
return wrapper- Right now the
include-list.luais split up into ...- Windows-system
- Linux-system
- OSX-system
- 3rd party libs Those OS-specific files themselves are split into:
- common internal include files whose cdefs shouldn't be duplicated.
- the main API include files that programmers use, and that themselves use those internal common files.
Right now previously generated files are searched for within new generated files, and the blocks are swapped out with
]] require 'ffi.req' ${include} ffi.cdef[[, so that the Luarequire()code can behave just like the C#includecode. The maintaining of the internal include files is tedious and always changing per SDK version change. However this could be automatic:
- Per each include file, search its include files, and search all previous binding generated include files (You'd have to store the preproc-output of each file, or at least keep track of the BEGIN/END comments that at the moment libwrapper-codegen is throwing out).
- If a duplicate is found then flag it for necessary generation ... insert it into some "needed internal system headers file ...
- If a previous internal header in that file is not found then flag it and report it that it can be removed.