All About Libraries in C Programming

All About Libraries in C Programming

Getting Started with C Programming

The C programming language is incredibly popular, and it's easy to see why. Programming in C is efficient and gives the programmer a great deal of control. Many other programming languages like C++, Java, and Python were developed using C.

Chances are increasing each day that if you're a programmer, you won't use C exclusively for your work. However, there are several learning C is highly beneficial, even if you don't use it regularly. Here's why:

  • You'll be able to read and write code for software that can be used on many different types of computer platforms, including everything from small microcontrollers to desktops, laptops, and mobile operating systems.

  • You'll better understand what high-level languages are doing behind the scenes, such as memory management and garbage collection. This understanding can help you write programs that work more efficiently.

The simplest way to define C is to call it a computer programming language, meaning you can write software with it that a computer can execute. The result could be a large computer application, like your Web browser, or a tiny set of instructions embedded in a microprocessor or other computer component.

C is what's referred to as a compiled language, meaning you have to use a compiler to turn the code into an executable file before you can run it. The code is written into one or more text files, which you can open, read and edit in any text editor, such as Notepad on Windows, TextEdit on a Mac, and gedit on Linux. An executable file is something the computer can run (execute). The compiler checks the code for errors and, if it seems to be error-free, creates an executable file.

If you're using Mac OS X and most Linux distributions (such as Ubuntu), you can add a C compiler to your computer if you install the development tools software for that particular OS. These free C compilers are command-line tools, which means you'll typically run them from a command prompt in a terminal window. The command to run one of these C compilers is "cc" or "gcc" plus some command line options and arguments, which are other words typed after the command before you press Enter.

For C, as for other computer programming languages, the version of the compiler you use is very important. You always want to use a version of the C compiler that's as new or newer than the version of the C language you're using in your program. If you're using an IDE, be sure to adjust your settings to make sure the IDE is using your target C version for the program you're working on

Sample C program

/* Sample program */
#include <stdio.h>

int main(){
printf("This is output from my first program!\n");
return 0;
}

When compiled and executed, this program instructs the computer to print out the line "This is output from my first program!" and then stop. You can't get much simpler than that! Now let's take a look at what each line is doing

Line 1 -- This is one way to write comments in C, between /* and */ on one or more lines.

Line 2 -- The #include command tells the compiler to look at other sources for existing C code, particularly libraries, which are files that include common reusable instructions. The references a standard C library with functions for getting input from a user and for writing output to the screen. We'll look at libraries more closely later.

Line 3 -- This line is the first line of a function definition. Every C program has at least one function, or a block of code representing something the computer should do when the program runs. The function performs its task and then produces a byproduct, called a return value, that can be used by other functions. At a minimum, the program has a function called main like the one shown here with a return value with the data type int, which means integer. When we examine functions more later, you'll see what the empty parentheses mean.

Lines 4 and 7 -- The instructions within a function are enclosed in braces. Some programmers start and end a brace-enclosed block on separate lines as shown here. Others will put the open-brace ({) at the end of the first line of the function definition. Though lines of code in the program don't have to be typed on separate lines, programmers typically put each instruction on a separate line, indented with spaces, to make the code easier to read and edit later.

Line 5 -- This is a function call to a function named printf. That function is coded in the stdio.h library included from Line 1, so you don't have to write it yourself. This call to printf tells it what to print to the screen. The \n at the end, within the quotes, isn't printed, though; it's an escape sequence that instructs printf to move the cursor to the following line on the screen. Also, as you can see, every line in the function must end with a semi-colon.

Line 6 -- Every function that returns a value must include a return statement like this one. In C, the main function must always have an integer return type, even though it's not used within the program. Note that when you're running a C program, you're essentially running its main function. So, when you're testing the program, you can tell the computer to show the return value from running the program. A return value of 0 is preferred since programmers typically look for that value in testing to confirm the program ran successfully.

What is a Library?

Libraries are very important in C because the C language supports only the most basic features that it needs. For example, C doesn't contain input-output (I/O) functions to read from the keyboard and write to the screen. Anything that extends beyond the basics must be written by a programmer. If the chunk of code is useful to multiple different programs, it's often put into a library to make it easily reusable.

In our discussion of C so far, we've already seen one library, the standard I/O (stdio) library. The #include line at the beginning of the program instructed the C compiler to load the library from its header file named stdio.h. C maintainers include standard C libraries for I/O, mathematical functions, time manipulation, and common operations on certain data structures, such as a string of characters. Search the Web or your favorite C programming guide for information about the C89 standard library and the updates and additions in C99.

You, too, can write C libraries. By doing so, you can split your program into reusable modules. This modular approach not only makes it easy to include the same code in multiple programs but also makes for shorter program files that are easier to read, test and debug.

To use the functions within a header file, add a #include line for it at the beginning of your program. For standard libraries, put the name of the library's corresponding header file between greater-than and less-than signs (). For libraries you create yourself, put the name of the file between double quotes. Unlike statements in other parts of your C program, you don't have to put a semicolon at the end of each line. The following shows including one of each type of library:

#include <math.h>

#include "mylib.h"

Why do we need libraries?

When we code a program, it tends to grow larger and larger every time we add more functionalities and so on, becoming a really big and difficult-to-read code. Once our program reaches this state, we start looking for different solutions to clean up and lightweight our code.

Here is where we start to think about combining our source code with small units of related files, that can be linked all together using different source code possibly by different programmers.

The C programming language is not limited to printing text to the standard output, we can access complex data, interact with the web, play with graphics, and more. The secret to doing that is to understand and use C libraries. Libraries can boost our C program’s potential. This libraries are found free on the internet, so we can download, install and use them.

Let us re-define libraries

First of all, we need to understand that one of the bunch of tools that compilers provide us is the libraries.

  • “A library is just an archive of object files. And is made up of useful and reusable code.”

  • “Is a collection of header files, exposed for use by other programs. The library, therefore, consists of an interface expressed in a .h file (named the "header") and an implementation expressed in a .c file.”

  • “If you have a bunch of files that contain just functions, you can turn these source files into libraries that can be used statically or dynamically by programs. This is good for program modularity, and code reuse. Write Once, Use Many.”

Types of C libraries:

  1. Static Libraries

Static libraries are just collections of object files that are linked into the program during the linking phase of compilation and are not relevant during runtime. This last comment seems obvious, as we already know that object files are also used only during the linking phase, and are not required during runtime — only the program’s executable file is needed to run the program.

1.1 Creating static libraries

  1. The first thing you must do is create your C source files containing any functions that will be used. Your library can contain multiple object files.

  2. After creating the C source files, compile the files into object files. gcc -c *.c

  3. Use Archiver to create the library with your files

ar rc libname.a *.o
This command creates a static library named libname.a and puts copies of all the object files in the current directory in it. If the library file already exists, it has the object files added to it, or replaced, if they are newer than those inside the library. The 'c' flag tells ar to create the library if it doesn't already exist. The 'r' flag tells it to replace older object files in the library, with the new object files.

  1. After an archive is created, or modified, there is a need to index it. This index is later used by the compiler to speed up symbol lookup inside the library and to make sure that the order of the symbols in the library won't matter during compilation The command used to create or update the index is called 'ranlib', and is invoked as follows:

ranlib libname.a

1.2 Using static libraries

After we created our archive, we want to use it in a program. This is done by adding the library's name to the list of object file names given to the linker, using a special flag, normally '-l'. Here is an example:

gcc main.o -L. -lname -o prog

This will create a program using object file "main.o", and any symbols it requires from the "name" static library. Note that we omitted the "lib" prefix and the ".a" suffix when mentioning the library on the link command. The linker attaches these parts back to the name of the library to create a name of a file to look for. Note also the usage of the '-L' flag - this flag tells the linker that libraries might be found in the given directory ('.', referring to the current directory), in addition to the standard locations where the compiler looks for system libraries.

  1. Dynamic/Shared Libraries

Shared libraries (also called dynamic libraries) are linked into the program in two stages. First, during compile time, the linker verifies that all the symbols (again, functions, variables, and the like) required by the program, are either linked into the program or in one of its shared libraries. However, the object files from the dynamic library are not inserted into the executable file. Instead, when the program is started, a program in the system (called a dynamic loader) checks out which shared libraries were linked with the program, loads them to memory, and attaches them to the copy of the program in memory.

The complex phase of dynamic loading makes launching the program slightly slower, but this is a very insignificant drawback, that is out-weighted by a great advantage — if a second program linked with the same shared library is executed, it can use the same copy of the shared library, thus saving a lot of memory.

A library can let us interact with the Operating System (OS), contain a collection of mathematical or logical operations, or do something else.

2.1 Creating Dynamic Libraries

The creation of a shared library is rather similar to the creation of a static library. Compile a list of object files, then insert them all into a shared library file. However, there are two major differences:

2.1.1 Compile for “Position Independent Code” (PIC) — When the object files are generated, we have no idea where in memory they will be inserted in a program that will use them. Many different programs may use the same library, and each load it into a different memory in address. Thus, we need that all jump calls (“goto”, in assembly speak) and subroutine calls will use relative addresses and not absolute addresses. Thus, we need to use a compiler flag that will cause this type of code to be generated.

In most compilers, this is done by specifying '-fPIC' or '-fpic' on the compilation command.

2.1.2 Library File Creation — unlike a static library, a shared library is not an archive file. It has a format that is specific to the architecture for which it is being created. Thus, we need to use the compiler (either the compiler’s driver or its linker) to generate the library and tell it that it should create a shared library, not a final program file.

This is done by using the '-G' flag with some compilers, or the '-shared' flag with other compilers.

  1. gcc command using the flag -c to generate the object files (.o) from the source files (.c) and the -fPIC to make the code position independent. Thus, the following command makes a bunch of .o files from each .c file in the current directory (You can select which functions you want for your library).

gcc -c fPIC *.c

  1. Next, we are going to put together those objects files into one library. To do this as a Dynamic Library we also use gcc but with the -shared option. The -o is to specify the name of the file you want it to have

gcc -shared -o libname.so *.o

  1. This way you must have your library created. To verify that you did it and have the right functions as dynamic symbols you can use:

    nm -D libname.so

2.2 Using a shared library

Using a shared library is done in two steps:

  1. Compile Time - here we need to tell the linker to scan the shared library while building the executable program, so it will be convinced that no symbols are missing. It will not take the object files from the shared library and insert them into the program.

    It is done almost the same as when linking with static libraries:

    gcc main.o -L. -lutil -o prog

    The linker will look for the file libutil.so (-lutil) in the current directory (-L.), and link it to the program, but will not place its object files inside the resulting executable file, 'prog'.

  2. Run Time - when we run the program, we need to tell the system's dynamic loader (the process in charge of automatically loading and linking shared libraries into the running process) where to find our shared library.

What are libraries used for?

  1. They allow code reuse.

  2. Provide special access to some aspects of the hardware or software.

  3. We should use them because the libraries have gone through rigorous testing and work, so they have been optimized to have a good performance.

  4. The portability of libraries enables them to work everywhere.