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.
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.oAbove 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.oAbove 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 statusThe 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.
mv libcalc_mean.so /home/cf/slibNow 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
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.
ReplyDeleteI tried your idea, produces some random value.
Delete"calc_mean.h" file just contains the declaration for the "mean" function which is included into "main.c" file.
ReplyDeleteI 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.
Amazing article.Cleanly written and well explained. I thoroughly enjoyed reading it.
ReplyDeleteHeader file needs to be inculded.. else it will take default to ints...
ReplyDeletewill .so (or dlls) have to supplied..its for your compiler that works before your program execution...
Rajat Paliwal
I am very much happy to read your blog. The explanation is crystal clear . Thanks for sharing the knowledge .
ReplyDeleteThe explanation is crystal clear. Thanks for sharing the info .
ReplyDeleteCleaned up the post with latest information and unwanted stuff
ReplyDeleteThank you very much. I searched the web few days for this kind of article. Easy to understand and well described. Thank you!
ReplyDeleteThat is great!
ReplyDeleteIf 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.
Good explanation. Very clear. That's what it makes for better understanding. Thank you.
ReplyDeletegood tutorial
ReplyDeleteThats the clever method to explain. I found what I was looking in other tutorial, which actually missing in them. very nice
ReplyDeleteI found what I was looking in other tutorial, which actually missing in them. very nice
ReplyDeleteWell explained tutorial ...
ReplyDeleteWell done! Simple and direct. What is, how to create and how to use.
ReplyDeleteThanks for this - it says what must be known without any "smalltalk".
ReplyDeleteA 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!
Hi,
ReplyDeleteJust 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.
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