Libraries in C: To prefix or not?

C's lack of namespaces makes using library code in higher level a bit too verbose for my taste. Some libraries, like RayLib, choose to not prefix the names, which causes a lot of headaches on Windows, and clashes with your own code, but the code is easy to write and read. Other libraries like SDL prefix everything, but that makes the code verbose. I've been trying to find a middle ground.

Let me start with an example of a drawing library that I share between projects:

codraw_aabb(
    &CORE->drawlist,
    (CoAABB){ 0, 0, 100, 100 },
    CoRGBA8_RED
);

codraw_text(
    &CORE->drawlist,
    &CORE->font,
    (CoV2){ 10, 10 },
    "Hello world!",
    CoRGBA8_WHITE
);

While this is alright, it still can be made cleaner:

draw_aabb({ 0, 0, 100, 100 }, COLOR_RED);
draw_text({ 10, 10 }, "Hello world!", COLOR_WHITE);

Thanks to this:

#ifdef CODRAW_DEFAULT
    #define COLOR_RED CoRGBA8_RED
    #define COLOR_WHITE CoRGBA8_WHITE
    // ...

    #define draw_aabb(...) codraw_aabb(CODRAW_DEFAULT, (CoAABB) __VA_ARGS__)
    #define draw_text(...) codraw_text(CODRAW_DEFAULT, CODRAW_DEFAULT_FONT, (CoV2) __VA_ARGS__)
    // ...
#endif

// Including 'codraw.h' library:

#define CODRAW_DEFAULT (&CORE->drawlist)
#define CODRAW_DEFAULT_FONT (&CORE->font)
#include <codraw.h>

Of course, not all tricks can be applied to every library. For game engine libraries though, this is a very handy approach, because it gives you best of the both worlds.

  • In tests, I use prefixed APIs and always create separate instances of dependent contexts or data.
  • As a library writer I no longer have to implement hidden static contexts that limits testing or assumes certain uses.
  • I got rid of "convenience" functions in the library too, as those can all live in the non-prefixed optional code.
  • In cases where I need to extend the APIs with my own functionality, or am writing another library, I'd always write prefixed variant that uses prefixed APIs but provide the default non-prefixed variant too.
  • In my high level game code I use the non-prefixed variant and allow the code to be easy to write and read.
  • This approach can also be applied to existing libraries which are already properly prefixed.
  • As a library user and owner of the "convenient" non-prefixed API I get to choose under_score or CamelCase or REtArD conventions by my own preference.

Library author:

  • Provides properly prefixed APIs.
  • Tries to not use globals or statics that would limit the use of the library.
  • Optionally provides non-prefixed APIs in the documentation, commented in header file or provides additional optional header file.
  • Ensures the prefix and names used do not clash as much as possible.

Library user when writing another depending library:

  • Same as library author above.

Library user in business code:

  • Defines his own non-prefixed APIs he's interested in casing mode they prefer.

Comments