The 2024 Wheel Reinvention Jam just concluded. See the results.

How do you make libraries easy to use

I have been struggling to figure out how some of the game development libraries can be used in other projects. I have my kiss-engine project, which really has some cool stuff, but currently it has some SDL2 and Freetype code. These are libraries, written to make some parts of the software easier, and yet I can not figure out anyway to put the code on github without it becoming a nightmare to use.

I hate when I find something and I need to install a bunch of other libraries that I don't want or need.

If these libraries are the answer to not writing everything from scratch, then why are they so hard to use, and how do you guys deal with this?
Personally I _hate_ SDL, not just because it's a pain to set up but also because there's so many corner cases where SDL just isn't quite right whether it's SDL_GetTicks() returning miliseconds when the native API's could potentially deliver microsecond accuracy or it's SDL making a fullscreen window span across multiple monitors because it abstracted away the common sense or it's crippling the functionality of some joystick by reducing it to the lowest common denominator etc. (these are all real-world examples I've encountered in games since they've been ported to SDL to achieve a 'cleaner' code base)

Other abstraction libraries are _less_ bad (eg. glfw3) but I think writing your own abstractions so you can make a conscious decision about what's reasonable really is the way to go, it usually ends up being a small part of the overall project if you commit to doing it from the start and keep it contained to the 'platform layer'.
For my own little game engine (Pixie Game System in the WIP forums) I've taken the approach to build all the significant parts as single header libraries, and just have the engine (which itself is a single header lib, although with dependencies on other single header libs) be mostly wrappers and glue code. Seems to be quite a good compromise - the engine itself is a monolithic all-or-nothing framework, which is fine for most of my game making, but when I'm writing something simpler or less run-of-the-mill, I can revert to using the base libs.

It does require thinking about the libs in a certain way though - make each module a truly separated lib which doesn't depend on any of the others. This means some code duplication, which seems to scare some people more than it should :P

I am also not particularly fond of SDL (for one thing, I think it does way too much), and have written my own lib to abstract the platform specific parts - it is very simple though, as all I need is to be able to give it a single bitmap and have it draw it to the screen, and give it a single sample buffer and play it. Everything else, like rendering, audio playback/mixing, gamepad input etc is done by other modules - which are not aware of the platform module - the glue code and wrappers are there to tie them together and pass data between them.

I've been meaning to post my source code for a while now, will try to get around to it soon, so I can have an example to point at :P
Forget about SDL for the moment, it seems that for any opensource library to be used, it can't depend on other libraries. "stb" header files specifically don't use any other dependencies, which is why they are so popular.

It seems like the whole point of libraries doesn't solve any problems at all. Am I missing something?
timothy.wright
it seems that for any opensource library to be used, it can't depend on other libraries.

This is so not true. There are a ton of opensource libraries used everywhere. Look at Linux - most of stuff it consists is an open source libraries and programs that depend on each other.

"Library" is just a collection of code. By saying libraries don't solve any problems at all you are saying that code doesn't solve problems? Apparently it solves somebody's problem, because otherwise that person wouldn't have put together his code and call it library.

Of course there will be bunch of people who don't like one particular or some other library. Either because lib is missing some features or they had trouble using it. But at the same time there are a bunch of people who uses same library perfectly fine.

Edited by Mārtiņš Možeiko on
mmozeiko
timothy.wright
it seems that for any opensource library to be used, it can't depend on other libraries.

This is so not true.


What!? that's absolutely true! Libraries definitely shouldn't depend on other libraries!
(lot's do, but they're just bad libraries) A library should do a thing, if it's just calling _some other library_ to do the thing then what is even the point in it?

Edit: and if the library needs something to do it's job, it should let you provide that function by having you set some function pointers or whatever so _you_ can choose how that requirement is fulfilled and whether using another library is the way to do it.

Edited by Michael Cameron on
I'm not talking how it should be. Or which are good and which are bad libraries. That's not my point.
I was replying to this:
it seems that for any opensource library to be used, it can't depend on other libraries.
There are a bunch of open-source libraries used that depend on other libraries.

Edited by Mārtiņš Možeiko on
mmozeiko
I'm not talking how it should be. Or which are good and which are bad libraries. That's not my point.
I was replying to this:
it seems that for any opensource library to be used, it can't depend on other libraries.
There are a bunch of open-source libraries used that depend on other libraries.


Oh, well yeah, and that's a problem (imo).

timothy.wright
It seems like the whole point of libraries doesn't solve any problems at all. Am I missing something?


I guess so? they're code that you don't have to write yourself, that's pretty much all there is to it? actually I guess you're right in a sense that there really isn't any point to _precompiled_ open-source libraries (besides maybe shaving some compile time?) since copy-pasting the code would accomplish the same thing.
mmozeiko
I'm not talking how it should be. Or which are good and which are bad libraries. That's not my point.
I was replying to this:
it seems that for any opensource library to be used, it can't depend on other libraries.
There are a bunch of open-source libraries used that depend on other libraries.


I think if you buy into the notion of a library 'solving' a certain problem once-and-for-all, interdependence is inevitable. But there are other ways of looking at it.

Look at the problem of video playback, for example. You need to be able to connect to a server and download the video stream or load the file from the filesystem. You need to parse the video stream into a raw feed. You need to decode the feed to individual frames. Then you need to display those frames on the screen with the right timing.

All of those things could be individual libraries. And there probably are. And all of them need to be able to communicate with each other. If you assume there will only ever be one library that does each piece of that, then there's no reason not to just have each other part of the pipeline call directly to the parts before and after it using the respective APIs. Technically each one could stand alone but because you assume that the other parts are static, you introduce cross-dependency.

But there's another way of looking at it. Each piece of that could be considered a 'service' of sorts, that produces and consumes a stream. The filesystem loader outputs an encoded video stream. The video decoder takes in an encoded video stream and produces a raw image stream. The display piece takes a raw image screen and puts it on screen.

However in order for that vision to work, there needs to be a common way to communicate so that they don't each need each others' API. The GStreamer library is one solution to this problem. It provides a framework for video streaming plugins to communicate with each other, and as long as every plugin is developed to work with gstreamer, it can tell gstreamer what kind of video it produces and what kind it consumes.

But that requires everyone to agree, and makes the common point a common dependency. If this was part of the operating system, that wouldn't be an issue. But none of the operating systems provides this service. Perhaps future operating systems should?

In any case, most problems are not solved in a single way, and often have interconnections with other problems or systems. So I think it's unrealistic to say a library should never depend on another library. But there are ways to mitigate dependence, and make it manageable.
ChronalDragon

However in order for that vision to work, there needs to be a common way to communicate so that they don't each need each others' API. The GStreamer library is one solution to this problem. It provides a framework for video streaming plugins to communicate with each other, and as long as every plugin is developed to work with gstreamer, it can tell gstreamer what kind of video it produces and what kind it consumes.

But that requires everyone to agree, and makes the common point a common dependency. If this was part of the operating system, that wouldn't be an issue. But none of the operating systems provides this service. Perhaps future operating systems should?

In any case, most problems are not solved in a single way, and often have interconnections with other problems or systems. So I think it's unrealistic to say a library should never depend on another library. But there are ways to mitigate dependence, and make it manageable.


iirc, DirectShow serves a similar role (to GStreamer) on Windows?

Also this raises the question when should something be a library and when should it be a process? if you've got an OS standardized interface for filters/codecs/streams then it seems logical to make that an IPC interface and push that data through sockets rather than having a library since you probably want to support all available codecs (so static linking is out) and support interchange with other applications (so IPC is needed).

I'm inclined to say that nearly everywhere you would want to use a _dynamic_ library a separate process is likely a better choice.

Unfortunately OS IPC interfaces really aren't as nice as I would like so as for future operating systems - I think an IPC/IO mechanism that provides a self-describing API would be a great start, eg. you should be able to query what functions(verbs) an interface provides, their type signatures, any data structures it uses(nouns), etc. Similar to what you might do with dynamic linking via GetProcAddress() and some functions to return meta-type tables and available function headers. I figure the number of interfaces that use a library to abstract their protocol from developers is a good testament to peoples preference for APIs over having to manually generate streams of tokens and decode packets so it's about time the OS just provided a proper mechanism to do this already.
DirectShow is deprecated. Its replacement is Media Foundation.
mmozeiko
DirectShow is deprecated. Its replacement is Media Foundation.


But does that actually mean anything? are they going to drop support for it? is the new thing in anyway better? at one point I looked on MSDN and they said OpenGL was deprecated (seems they've fixed that, Edit: hmm, actually maybe they just said 'legacy'?). I guess I'm wondering, to Microsoft, does deprecated actually mean anything other than "this isn't the latest C++/C# garbage we dreamed up"?

Edited by Michael Cameron on
In this case deprecated means no new features are added, no bugfixes are done (unless is some critical security issue). All the new features, codecs, performance improvements, integration with other API goes into MF.

Of course, old code using DS will still work fine.

Unless you need to support Windows XP you should probably pick MF over DS when writing your app. Just like you should pick D3D11 API over D3D9 API.

Edited by Mārtiņš Možeiko on
chronokun

Oh, well yeah, and that's a problem (imo).


Suppose I write a deep learning library, and one of the things I want to do is visualize the networks.
Because I am already making a library, I can't then depend on any kind of rendering or UI library and have to start that from scratch?

Or do you mean that I should be sure to include the dll/library whatever in my lib, so that people don't have to go install it separately?
MandleBro
chronokun

Oh, well yeah, and that's a problem (imo).


Suppose I write a deep learning library, and one of the things I want to do is visualize the networks.
Because I am already making a library, I can't then depend on any kind of rendering or UI library and have to start that from scratch?

Or do you mean that I should be sure to include the dll/library whatever in my lib, so that people don't have to go install it separately?


In this case I would suggest that UI rendering doesn't belong in a library for deep learning, perhaps there is something really special and about a deep learning UI and if that's the case perhaps two libraries might make sense but I can't think why a deep learning library would need a UI to be usable, seems like it would only get in the way? wouldn't the user want to create their own UI for their application or use a library of their choice to create one? Also if you needing to use this deep learning library in a situation not requiring a UI where it is being controlled in some other way were you thinking the UI would be the only interface to the library?

As for visualization, I think being able to provide sufficient information about the networks from the library would be enough for people to create visualizations trivially from that, but if you wanted, you could always include that either as a separate lib, or even just as an example usage application with code they can copy and reuse if they wish.

But generally if I _do_ have dependencies I would include them with the code but in this case I would just say a library should do _one_ thing.

Edited by Michael Cameron on