Apologies for the long pause in the header files series and in blogging in general. With the holidays in between and, especially, with my refreshed energy to do stuff in the FreeBSD and Kyua camps, I haven’t had any reasonable amount of time to write. And, sincerely, with my very limited free time I really cannot cover it all. So… these days, coding it is thus expect a reduced blogging pace!
As we saw in the previous post, header files are a poor system to implement real modules. In particular, any identifier defined in a header file becomes “public” to any translation unit including such file. This, of course, comes with implied dangers in name collisions and symbol redefinitions.
There is no way to prevent this, so let’s see some simple workarounds.
The only workaround you have in C is to fully qualify your identifiers with a prefix that hopefully is unique within any code that may require your headers. In the general case, it is often good enough to just use your project name as the prefix: for example, for a project
libfoo, you would use a
foo_ prefix in all of your identifiers.
Avoid the temptation to shorten your project name to a single letter. There are only so many letters in the alphabet so you—or, worse, the users of your code—are guaranteed to experience collisions with some other library at some point in the future.
On the other hand, there is no real benefit to go to great extents like in Java where namespaces include a domain name that you control so as to enforce globally-unique names. In fact, doing this in a language like C would result in a completely unusable API due to extremely-long identifier names.
Things are slightly better in the C++ camp due to the existence of namespaces. Installable header files should define everything they provide within a project-specific namespace.
There is one caveat that many people seem to forget: macros (and other preprocessor symbols)! Defining a macro within a namespace does not make it specific to the namespace. Macros are “global” by default due to the fact that… well… they belong to a separate language and are processed separately (n.b. not the case in clang, but that’s a separate story). So, for macros, you will have to do the same as in C and prefix them explicitly with your project name. It’s ugly, so bonus points if you can avoid providing macros altogether.