Take a complex C library which was written ages ago, not written specifically to be used by Lua or Python or whatever, with an enormous number of functions.
You can:
- Try to write a wrapper dylib over it in C which calls the other C library and focuses on all the binding work necessary to make that a proper and idiomatic Python or Lua module, e.g.
- Just be able to use the library right away in Lua or Python or any other language through the FFI and test it, play with it, experiment, start wrapping it, etc.
The second option is pretty appealing to me. Also you don't have to use the FFI directly. You can still, for example, use LuaJIT's FFI to directly call C functions behind a nice Lua table which conforms to Lua idioms (1-based indexing, e.g.). I actually find that takes far less time wrapping FFI code to be idiomatic than exporting a proper Lua librarymodule which has to translate everything to tables and numbers and so on using Lua's C API to build a conforming Lua module.
The FFI lets you do more of your work directly in the language you're targeting. The alternative will inevitably require you to spend a whole lot more time in C.
Take OpenGL as an example and let's just pretend there were no OGL Lua modules already available. In that case, with LuaJIT's FFI, you could be drawing shapes to a viewport in no time by just directly calling OpenGL functions through the FFI. Soon you might start wrapping it into Lua tables with nice functions suitable for your application. Otherwise you might have to spend an entire weekend or longer binding and translating a boatload of OpenGL functions, constants, etc. in C to build a miniature Lua module with only a small subset of OGL functionality and then import that just to get a triangle on a screen, only to then have to bind more functions and so on.
It is far, far more time-consuming to get started trying to export a conforming module to your language as opposed to just being able to call C APIs directly from it right off the bat. That applies even if you use things to help with the binding like Boost.Python or luabindLuaBind. It's an extremely time-consuming process to do properly, and FFI bypasses all of that.
I actually think FFI is the way to go and would prefer that over exporting modules specific to a language. As an example, some users wrapped my SDK to allow them to call its C functions from C#. I never had to write a C# or .NET module to let them do that. They just directly call my C functions from C#'s FFI which lets them import C functions from dylibs and call them right away.