Why are there so many bad C libraries?
I want to complaint for a bit. The title says enough for you to know about what.
In my experience with embedded software, sometimes you just don't want to write something yourself. This is very normal and in any environment, be it .NET, Node or somewhere else, I would not hesitate. With C (and to some extend C++) I do every time.
Making it compile
First you need to decide whether to just copy the code to your own project or properly compile and link with it. Of course you just copy it because the library is just 4 files and you don't want to complicate the way that compilation currently works. Also, the vendor locked-in environment you're using doesn't provide a simple way to do it properly anyways.
After that, you of course want to use the library in your code and you #include it in two of your files. Compile error. Why? Because even though the library is just 4 files, the author seems to have messed up and did not put everything behind proper header guards. You look at the documentation to figure out why and it seems the author only ever statically linked against his own library.
You're pretty done with it already, so you do a quick fix. Now you're finally ready to start using the library. The first thing you notice is that the library must be initialized first using a ridiculously big configuration struct. All fields have weird names but luckily there are some comments next to them to explain what they are. What it doesn't say, though, is what sane defaults are and there doesn't seem to be a function that instantiates a configuration struct for you. So now you're looking at the field
int mDeltaAckCount and start wondering if the
-AckCount defines in the header are valid values for it. You just pick one that is defined as a 0 and hope that that will be good enough.
The initialization function gives you a struct back. You need to pass it to any library function you want to use. The functions also don't just return a value, they return only an error value. If you want to get the result of an action, you need to read out one or more fields of the struct. So you look at that struct and see it's huge! Screen filling. Not only does it have all the results you'd ever need from the library, it also has dozens of private variables. But it's C, so they're not really private. They have a comment saying it is and a
You are really done with this library now. But luckily for you, it did it's job. Your code is working. Or at least you thought so until you found a bug two weeks later. When digging into the code, you come to the conclusion that this library always calls a 'central' function from any function you call and that only the state of the struct determines what the library will do. So debugging is your only option as simply reading the code is not viable.
In the end, you regret using this library and would've rather written it yourself.
Like I said before, in other environments like Rust, I've never had this issue. There are good C(++) libraries of course, but as soon as your needs are more niche and there is no big known library there, then the quality is just a coin-flip where the options are not just the two faces of the coin, but also dropping the coin and having it fall in a drain.
What's the moral of this story about an imaginary library? Well, never trust any code to be good, especially when the language or platform it's for doesn't have good universal tooling to help make it good.
Want to see a big struct like I talked about? Here's an example from the LMIC library.