💾 Archived View for gemini.ctrl-c.club › ~stack › gemlog › 2022-08-09.impedance.gmi captured on 2023-07-10 at 14:35:10. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

Impedance Mismatch in Bindings

I love working Common Lisp. Instead of compiling stuff and trying it out, I can dynamically change things -- often while the code is running -- to see how things would look in a game, for instance. Compare that to compiling a few dozen times just to get the layout of something right.

There are many C libraries which may be usable in Lisp via foreign-function-interfaces or bindings. The quality of the bindings varies with the abilities of the coders writing the bindings, and the level of understanding of the overall system, especially the C end of it.

Unfortunately, the issue I call 'impedance mismatch' for the lack of a better term, comes up often when using FFIs.

I've been messing around with Raylib, a neat support library for making games. The 'cl-raylib' library is a handcrafted layer translating raylib's C calls to Lispy equivalents. It is a non-trivial effort, and I am very grateful to the author. However....

RGBA hassles

Many (if not all) raylib drawing calls take a color parameter. In raylib (C), a color is represented by a 4-byte value, containing each of the Red, Green, Blue, and Alpha components. An RGBA conveniently fits into 32 bits. In C it is represented by a simple struct, with unsigned byte components, for easy access to the elements; the entire struct can be passed by value in a register.

In Lisp, the default way of handling C structs, is to take them apart and convert them into lists. So a 4-byte RGBA value in C is converted to a 4-element list (r g b a). Sounds innocent enough, but it is now a linked list, and each of the elements is a 64-bit (8-byte) value, and an 8-byte pointer, adding up to 64 bytes.

To make matters worse, the 4 elements are likely in different parts of the memory, and just walking the list will trash 4 cache lines.

So cl-raylib's list of stock colors eats up 64 bytes each. Every drawing call into raylib requires, just for the color parameter, walking the list and packing a 32-bit value. Translating colors back from C (I doubt that happens much, but still) requires consing up a fresh list from a 4-byte value.

Clearly this is a bad way to deal with colors. It makes a lot more sense to keep colors as 32-bit integers, and have a couple of routines to pack and unpack them to lists if that is ever necessary. Or better yet, a few macros to access bytes directly as needed.

It took maybe 10 minutes to change the code with search/replace. I've been waiting for the maintainer to look at the PR for a couple of days now, hopefully it will be done. Otherwise I will have to fork and maintain my own version of the bindings.

I tried to be super sensitive with the maintainer to avoid the face-saving head-clashing that often ensues in such cases.

index

home