Up to this point, all the awesome library’s header file has are the forward declarations for the library’s functions:
/* awesome.h Header file for the awesome library. */ #include "simpletools.h" // Include simple tools int awesome_getCount(void); void awesome(void); void epic(void); int awesome_startTimer(void); void awesome_stopTimer(void); int awesome_secondsSince(void); int awesome_secondsReset(void);
We can add two more features to make our library robust:
- Include Guard
- C++ compatibility block
The Include Guard
An include guard prevents compiler errors that could result if two different parts of an application #include the same header file. Without a guard, the C preprocessor could end up trying to process the header twice if two different libraries #include it. With a guard, the C preprocessor keeps the information from the header with the first #include, and skips it the second time because it sees the guard.
An include guard looks like this:
#ifndef UNIQUE_NAME_FOR_HEADER_FILE // Include guard #define UNIQUE_NAME_FOR_HEADER_FILE ...All header file declarations... #endif // End Include guard /* UNIQUE_NAME_FOR_HEADER_FILE */
The first lines say "if the UNIQUE_NAME_FOR_HEADER_FILE macro name has not already been defined, keep going, otherwise, skip everything until #endif is reached."
The first time the preprocessor goes through the header it will process all the information. Since one of the items in there is #define UNIQUE_NAME_FOR_HEADER_FILE, that macro name will be defined. So the second time it tries to process that header, it’ll see the #ifdef, realize that UNIQUE_NAME_FOR_HEADER_FILE is already defined and skip it.
The C++ Compatibility Block
The header information should also be placed inside a block of code that allows it to be used by a C++ compiler. A C++ compiler updates function names with some additional information to support a C++ feature called overloading, but this can cause compiler errors when used on C code. The compatibity block code tells a C++ compiler to just compile the function names with C instead of C++.
#if defined(__cplusplus) // If compiling for C++ extern "C" { // Compile for C #endif ...All header file declarations... #if defined(__cplusplus) } // End compile for C block #endif /* __cplusplus */
If SimpleIDE’s compiler is set to C++ in the project settings, __cplusplus will automatically get defined. In that case, #if defined(__cplusplus) will add extern “C” { above the header info and } below it, so that it gets compiled without the extra overloading information and the compiler errors that would cause.
Add Features to awesome.h
Let’s apply the include guard and C++ compatibility block to awesome.h.
- Update awesome.h as shown below.
- Leave the Compiler Type set to C, not C++
- Recompile for the memory models you plan to use (CMM, LMM, etc.).
/* awesome.h Header file for the awesome library. */ #ifndef AWESOME_H // Prevents duplicate #define AWESOME_H // declarations #if defined(__cplusplus) // If compiling for C++ extern "C" { // Compile for C #endif #include "simpletools.h" // Requires simpletools void awesome(void); // Forward declarations int awesome_getCount(void); int awesome_startTimer(void); void awesome_stopTimer(void); int awesome_secondsSince(void); int awesome_secondsReset(void); void epic(void); #if defined(__cplusplus) } // End compile for C block #endif /* __cplusplus */ #endif // End prevent duplicate forward /* AWESOME_H */ // declarations block
Congratulations! Now there's only one thing left to do: optionally document your library to make it easier for other people to use (and easier for you to remember what you did!)