I need to create an API that will allow my customer\'s developers to use a proprietary C module that will be released as a library (think .lib
or .so
-
Consider putting the docs online, in addition to whatever ships, and put the URL in the header. This will allow some maintenance programmer, several years down the road, access to the docs, even if the originals have been lost.
The header file itself should be clean and tidy and probably close to minimal. It should point to where the documentation can be found. It probably shouldn't include complete examples (notwithstanding some of my own headers that do that). It should include basic information about the copyright and licence and author details. It should only contain stuff that end users need - nothing that only the developers need. It should be self-contained; it should include any other headers necessary to make it work (so the user can write '#include "your-header.h"
' and the code will compile cleanly, even if that's the first or only header they include).
Added: The header should include some basic version information too (file revision number and modification date, and/or the product release version number and release date). This helps people looking at two releases of the software -- and successful software is released more than once.
Added: Adam asked me to expand on "and nothing that only the developers need". That means, for example, that even though the internal functions may use some structure type, if none of the external interfaces uses that structure type, then the public header should not contain a definition of that structure type. It should be in a private header that is not distributed (or is only distributed with the complete source). It should not be polluting the public header. It is tempting to say "but it is only a little bit of wasted space", and it is accurate, but if everyone wastes a little space and time, then the total waste can become expensive.
The key point about the public header is that it should contain everything that the user of the library (set of functions) needs, and nothing that they do not need.
Consider actually writing separate documentation. I think man/info pages provide a good example as to what API docs should be like.
Other people mentioned documentation concerns, so I'll stay away from those :-P. Firstly, make sure you have sane include guards. personally I tend to like:
FILENAME_20081110_H_
, basically the filename in all caps, then the full date, this is help ensure that it is unique enough, even if there is another header in the tree which has the same name. (For example, you could imagine two config.h's included from 2 different lib directories having guards which use CONFIG_H_
or something like that and thus having a conflict. It doesn't matter what you choose, so long as it is likely to be unique.
Also, if there is any chance this header will be used in a c++ project, please wrap your headers in blocks like this:
#ifdef __cplusplus
extern "C" {
#endif
/* your stuff */
#ifdef __cplusplus
}
#endif
This will save some headaches with name mangling issues and make it so they don't have to wrap the header externally with these.
One option is to generate the API documentation from the header using (for instance) Doxygen. Obviously you'd still ship the docs alongside the code.
This gives you two advantages:
1) You don't worry so much about whether something should be "in the documentation" or just "in comments in the header", because changing one is just as easy as changing the other. So everything goes in the documentation.
2) Users are less likely to go reading your header file in the first place, because they can be reasonably confident that everything of interest is in the documentation. But even if they're die-hard "I don't trust docs, I read the code" types, then they still see everything you want them to see.
The downside of auto-generated API docs is that they can be a nightmare to search, so IMO it's worth putting additional effort into writing really good "introductory" documentation. This may or may not be part of the generated API docs, depending what you prefer. For a small API, just a list of all the functions in "logical" rather than alphabetical or source order, described according to what they're for rather than what they do, can make it much easier to get into the API docs. By "logical", I mean list the commonly-used functions first, in the order that a client would call them, with alternatives which "do the same kind of thing" (such and send and sendTo for sockets) grouped together. Then list the less-commonly-used functions, and finally the obscure stuff for advanced users and unusual use cases.
One major difficulty of the approach, which can be a show-stopper, is that depending on your organisation you may have a docs team, and it may not be possible for them to edit the header. Best case scenario then is that they copy-edit what you've done and you make the changes and feed them back. Worst case scenario is the whole idea grinds to a halt because "only the docs team are supposed to write customer-facing documentation, and it must be in standard format, and we can't make Doxygen output that format".
As for "what else should you consider" - you've already said you'll follow best practices, so it's hard to add much :-)
Please pretty please make sure you don't (re)define symbols that might be defined anywhere else. I don't mean just the standard names, please prefix all symbols declared/defined in public headers with a specific string and avoid any name that anybody else might have ever though about using.
I say this after seeing too much craziness like this in "professional" publicly available headers:
typedef unsigned short uchar;