togFox wrote: ↑Sun Jun 06, 2021 9:29 pm
At risk of hijacking this thread, are there some examples of using ffi in Love?
For an example of using the functions, see nativefs cited in this thread. For an example of using just the structures but not the functions, see the GifLoad library in my sig.
togFox wrote: ↑Sun Jun 06, 2021 9:29 pm
How do you find/discover external functions, determine there requirements and then invoke?
These are three separate problems.
1) Find/discover external functions: You need some basic understanding of dynamic libraries and public symbols. There are two cases to contemplate:
1a) The functions are already included as part of Löve, so you don't need to import external libraries (I heard that with Windows you still need to load the executable as a FFI library though; in Linux there's no such need). That's the case of the C standard library and everything that Löve has built-in, for example PhysFS. In this case, it's the Löve executable or the Löve library that provides the symbols.
1b) The functions belong to an external library. In this case, it's the library that provides the symbols.
In Linux you can use `nm <filename>` to list the public symbols that an executable or dynamic library exports. I guess other systems have other tools. With that, you can know which functions are exported by the file. You can run it on the Löve executable or on a dynamic library. Here's what it lists in my case for the Löve executable:
http://www.formauri.es/personal/pgimeno ... ymbols.txt
For several reasons, don't even try to invoke C++ functions. Use only C functions. I've removed most C++ symbols from the list for brevity, as there are ~12,000 of them. For the ones that have @@ in them, only the part before the @@ counts.
2) Determine their requirements (the signature of the function, or the prototype in C). This is not always possible, but for free software or software with API documentation, you can go to the source code, or the documentation, and look for the declaration. The API of the C standard library in particular is documented in many places. You then write that as a string into your code and pass it to ffi.cdef(). The declaration needs to be entered with C syntax, so if you try to use a library written in some other language, you need to translate it to C syntax.
3) Invoke. You have to make sure that you pass the right types and parameters to the function. C checks the types, order, etc. of your parameters at compilation time, but in FFI there's no compilation time and no checks, so you have to be careful. You need to create the structures with the appropriate types that the functions expect. For that, ffi.cdef accepts a wide subset of C. In some cases you can just pass the .h of a library to ffi.cdef directly (assuming it has no preprocessor commands).
A Lua library will typically sweep these details under the rug of the library itself, exposing to its users only a tidy and simple interface. See for example
https://github.com/hamishforbes/lua-ffi ... i-zlib.lua, which is a LuaJIT FFI wrapper to use the ZLib compression library in Lua, or
https://github.com/ColonelThirtyTwo/lsq ... qlite3.lua which is the same for the SQLite3 library (the latter is incomplete).
togFox wrote: ↑Sun Jun 06, 2021 9:29 pm
And curious what happens when you get that wrong? Love dies a horrible death or a neat trace stack is produced?
Almost always the first. FFI is raw low-level access to functions.