/* Ajith - Syntax Higlighter - End ----------------------------------------------- */

12.09.2009

Creating and using shared libraries in Linux

What is a Shared Library ??
A library that is loaded into physical memory only once and reused by multiple processes via virtual memory. 
Generally Shared libraries are .so (or in windows .dll) files.

Why shared libraries ??
  • They reduce memory consumption if used by more than one process, and they reduce the size of the executable.
  • They make developing applications easier: a small change in the implementation of a function in the library don't need the user to recompile and relink his application code every time. You need to only relink if you make incompatible changes, such as adding arguments to a call or changing the size of a struct.
NOTE: Debugging using a shared library is slightly more difficult when compared with static libraries, because the debugger usually used on Linux, gdb, has some problems with shared libraries.

Let us see how to create a shared library on Linux. We use following source code files for this post.
calc_mean.h
#ifndef calc_mean_h__
#define calc_mean_h__
double mean(double, double);
#endif  // calc_mean_h__
calc_mean.c
double mean(double a, double b)
{
return (a+b) / 2;
}
main.c - We are including our shared library in this application.
#include <stdio.h>
#include "calc_mean.h"

int main(int argc, char* argv[]) {

double v1, v2, m;
v1 = 5.2;
v2 = 7.9;

m  = mean(v1, v2);

printf("The mean of %3.2f and %3.2f is %3.2f\n", v1, v2, m);

return 0;
}

1. Creating Object File with Position Independent Code
All the code that goes into a shared library needs to be position independent. We can make gcc emit position-independent code by passing it one of the command-line switches -fpic or -fPIC (the former is preferred, unless the modules have grown so large that the relocatable code table is simply too small in which case the compiler will emit an error message, and you have to use -fPIC).

First we will create object files for all .c files that goes into a shared library.
gcc -c -fPIC calc_mean.c -o calc_mean.o
Above we are compiling calc_mean.c with -fPIC option and generating calc_mean.o object file.

2. Creating Shared library with the Object File
Every shared library has a prefix "lib", the name of the library, the phrase ".so", followed by a period and a version number that is incremented whenever the interface changes (as a special exception, the lowest-level C libraries don't start with "lib").
gcc -shared -o libcalc_mean.so calc_mean.o
Above command on successful produces a shared library named "libcalc_mean.so".
  • -shared: Produces a shared object which can then be linked with other objects to form an executable.

3. Using the Shared Library
Now let us link the created shared library with our application. Compile main.c as shown below
$ gcc -o test main.c -lcalc_mean
/usr/bin/ld: cannot find -lcalc_mean
collect2: ld returned 1 exit status
The linker doesn’t know where to find libcalc_mean. But why ?
GCC has a list of places to look by default for shared libraries, but our directory is not in that list. Bingo that's the reason compilation failed at linking level.

Now we need to tell GCC where to find libcalc_mean.so. We will do that with the -L option.
gcc -o test main.c -lcalc_mean -L/home/cf/slib
  •  -l option tells the compiler to look for a file named libsomething.so The something is specified by the argument immediately following the “-l”. i.e. -lmean
  • -L option tells the compiler where to find the library. The path to the directory containing the shared libraries is followed by "-L". If no “-L” is specified, the compiler will search the usual locations. "-L." means looking for the shared libraries in the current directory and "-L/home/cf/lib" means looking for the shared libraries at "/opt/lib" path. You can specify as many “-l” and “-L” options as you like.
NOTE: It would be a better idea to move all personal shared libraries in one directory rather in the current directory. For easy understanding I am moving "libcalc_mean.so" to "/home/cf/slib".
mv libcalc_mean.so /home/cf/slib
Now compile main.c. It would be successful and creates an executable named "test".
Let us check if the path to our shared library is included successfully into the executable by linker as shown below.

ldd executablename
$ ldd test 
 linux-gate.so.1 =>  (0x00332000)
 libcalc_mean.so => not found
 libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x006aa000)
 /lib/ld-linux.so.2 (0x00db9000)
You can see that linker cannot find our shared library libcalc_mean.so.

Basically libraries are present in /usr/lib amongst other places. Static libraries (.a suffix) are incorporated into the binary at link time, whereas dynamic ones (.so suffix) are referenced by location.

Check the PART2 of this article to understand further

19 comments :

  1. We dont need to declare the header file "calc_mean.h" in the main.c file because we are any how linking the object file dynamically.

    ReplyDelete
    Replies
    1. I tried your idea, produces some random value.

      Delete
  2. "calc_mean.h" file just contains the declaration for the "mean" function which is included into "main.c" file.

    I dont say it is mandatory but good coding practice to declare a function before we use. Offcourse still we can successfully compile the code but come across warnings.

    ReplyDelete
  3. Amazing article.Cleanly written and well explained. I thoroughly enjoyed reading it.

    ReplyDelete
  4. Header file needs to be inculded.. else it will take default to ints...
    will .so (or dlls) have to supplied..its for your compiler that works before your program execution...
    Rajat Paliwal

    ReplyDelete
  5. I am very much happy to read your blog. The explanation is crystal clear . Thanks for sharing the knowledge .

    ReplyDelete
  6. The explanation is crystal clear. Thanks for sharing the info .

    ReplyDelete
  7. Cleaned up the post with latest information and unwanted stuff

    ReplyDelete
  8. Thank you very much. I searched the web few days for this kind of article. Easy to understand and well described. Thank you!

    ReplyDelete
  9. That is great!
    If you contrasted it with the command to statically the same, it would have been a complete tutorial. I found after some trial and error that this works.
    gcc -o static_main.out main.c -L/home/cf/slib calc_mean.o
    Thanks for the quick and effective tutorial.

    ReplyDelete
  10. Good explanation. Very clear. That's what it makes for better understanding. Thank you.

    ReplyDelete
  11. Thats the clever method to explain. I found what I was looking in other tutorial, which actually missing in them. very nice

    ReplyDelete
  12. I found what I was looking in other tutorial, which actually missing in them. very nice

    ReplyDelete
  13. Well explained tutorial ...

    ReplyDelete
  14. Well done! Simple and direct. What is, how to create and how to use.

    ReplyDelete
  15. Thanks for this - it says what must be known without any "smalltalk".

    A question to the nerds:
    Is it possible to use an initialization routine which is only called once when the library is called first time? And how can this be recognized?

    Thank You!

    ReplyDelete
  16. Hi,
    Just a little question. I tried to use this and but I'm stuck with another error. Even when I add the lib path and the include path it just says it can't find the header file. How can I fix this? Hope somebody could help.
    Thanks for the tutorial.

    ReplyDelete
  17. I have 1 question...when we create our shared library before moving it to the desired location where does it go...Is it the pwd or some other location..plz answer??

    ReplyDelete

Your comments are moderated