Pyllisp FFI Uses Generated JSON Headers
I got tired to scanning©/pasting through C header files for some while ago. It's stupid waste of time, and your usual C header got hundreds of messily formatted declarations.
Pyllisp FFI has a function
ffi.library, when you pass it just the path to the library it opens the library. Let's look into the interactive console of my latest pyllisp interpreter. The
pyl> denotes an input with output below:
pyl> lib = (ffi.library "libSDL2.so") <library>
It finds the libSDL2.so and dlopens it. Though it's quite useless. You don't have any type annotations, and pyllisp doesn't attempt to guess them.
pyl> lib.SDL_Init <handle SDL_Init from libSDL2.so> pyl> (lib.SDL_Init 0) Traceback: shell: 1:0 1:16 Error: cannot call null pyl> pyl> lib.SDL_INIT_EVERYTHING Traceback: shell: 1:0 1:23 Error: Not in the library: SDL_INIT_EVERYTHING
If you'd like to use this library, you have to annotate the handles. In Pyllisp FFI you could do it like this:
pyl> Init = (ffi.cast lib.SDL_Init (ffi.cfunc ffi.int [ffi.int])) <handle SDL_Init from libSDL2.so> pyl> (Init 0) 0
ffi.library has a feature to annotate the library right when you create it, check this out:
pyl> names = (dict) <dict> pyl> names['bob'] = 5 5 pyl> lib = (ffi.library "libSDL2.so" names) <library> pyl> lib.bob 5
Quite boring huh? Aside passing in constants, you may supply into the dictionary that the name wraps something:
pyl> names['Init'] = (ffi.wrap "SDL_Init" (ffi.cfunc ffi.int [ffi.int])) <wrap SDL_Init <cfunc <signed 4> <signed 4>>> pyl> lib.Init <handle Init from libSDL2.so> pyl> (Init 0) 0
Why have such feature in the FFI? It's there because in pyllisp, you're not supposed to annotate functions yourself. There's
api.open. Say you call
(api.open "libSDL2.so"), the following happens:
- Pyllisp searches for
libSDL2.jsonand decodes it.
- It is wrapped into a type resolver object. That object builds up type annotations when requested.
- Pyllisp calls for
ffi.openfor you, with the type resolver.
Here's an example of using the
pyl> sdl = (api.open "libSDL2.so") <library> pyl> (sdl.WasInit sdl.INIT_EVERYTHING) 0 pyl> (sdl.Init sdl.INIT_EVERYTHING) 0 pyl> (sdl.WasInit sdl.INIT_EVERYTHING) 29233 pyl> sdl.INIT_EVERYTHING 29233 pyl>
So where to get those
.json -files from and how do they look like? I wrote a tool to generate them from C headers, in python. The libSDL2.json sits in the repository too. Theoretically any language could use the same header files, as they follow the naming conventions set by the library and are minimally mangled. Just to get rid of namespace prefixes and redundant type annotations that are mandatory on C.
The tool isn't complete, I still have to try the bindings out and fix possible minor bugs there are in the generation. Otherwise it should simplify use of the C libraries.