More About Libraries







Up to this point in this tutorial, I've mentioned libraries several times. But what exactly is a library? A library is a collection of pieces of code designed usually for one purpose. Libraries include things like functions, defined constants, and macros. You've already seen some of the standard libraries that C uses; these include things like stdio.h, stdlib.h, and string.h. These libraries come with the standard distribution of C and are agreed upon as being standard, and so any code you write using them should be exportable. In this section, I'll show you how to create libraries of your own, which lets you split up a large program in to many smaller pieces.

Library How-Tos

First of all, any library consists of two parts: the header file (also called the interface) and the implementation. Headers typically end in .h, while implementations end in .c, just like normal programs. The header file contains very little actual code. The three pieces of information that belong in a header are a little preprocessor mumbo-jumbo, the function prototypes and any constants, and, most importantly, lots of comments. Everything in your header files should be fully documented, including what each function needs as arguments, what it returns, and what it does. Anyone coming along should be able to tell what the library functions are used for by reading the comments in the header file. Ideally, anyone else who uses your library should never look at the implementation. In this way, libraries become a way of hiding code from the user, so that they can use your functions without having to understand the guts of how they work. The implementation file is fairly straightforward: it contains the implementations of all the functions declared in the header file.

So lets look at an example library header:

/* Library my_lib.h
 * ----------------
 * This library provides a set of functions for some particular
 * purpose.
 */

#ifndef _my_lib_h
#define _my_lib_h

/* foo() does something */
void foo(void);

/* bar() does something else */
void bar(void);

#endif

Note the preprocessor directives you must put in. The arguments on the #ifndef and #define lines should be the name of your library preceded by an underscore and with any periods replaced with and underscore. At the end of the header, tack on a #endif. There. That wasn't too painful, was it?

Now to use these functions that you've declared in your .h file and implemented in your .c file, you simply throw the line #include "my_lib.h" at the top of your program (note that libraries you make yourself should be in double quotes, not angle brackets). Now you have access to everything defined in your library in your program.

Private Variables and Functions

Remember how I told you not to use global variables? Well, there is one way in which they're useful. Since a global variable's scope (the part of the program it belongs to) is the whole program, the memory used to hold its value is not deallocated until the program exits. What this means is that if you put a global variable into your library and assign it a value, it will retain that value between function calls. In this way, you can use global variables to save the state of something in your library. Libraries used like this are often called modules. But since this variable is now doing the equivalent of holding your place in the module, you don't want some user to come along and change its value and mess everything up. To avoid this, you can make it private to the module by using the static keyword before its declaration, like so:

static int Some_Global;

The static keyword should really be named private; it has the effect of letting only functions from within its own module affect it. It also means that there is no problem if the user declares a variable with the same name elsewhere in their own program, because the two variables will now be separate. You can also use the static keyword with functions. This is mostly used because of the naming issue. In general, the safest way to code is to declare every global variable and everything function to be static unless you are specifically exporting them. Thus, you don't want to make the functions in your library static, but if you need any "helper" functions to implement them, those should be declared static. It doesn't even hurt to declare all globals and functions in your own program as static; that way you avoid the issue of problems with names.



Back to Functions   On to Section 2: More Abstraction
Back to the Outline