Linux World

Thursday, April 17, 2008

A quick tour of writing shared libraries for Linux

Its easy. The libraries in Linux world are called as Shared Objects thats why each library file name is like x.so.
Ok so let us get our hands wet with shared objects. We will implement a small shared lib, which will provide only one function named "myprint". The function myprint takes a pointer to string and prints that onto the std output. Here comes the prototype of "myprint":
int myprint (char *str);
Let us follow the steps below in order to get our library on the board.

Step 1: Code the library. Write a file mylib.c

#include
int myprint (char *str)
{
return printf (str);
}

Step 2: Compile mylib.c using gcc with appropriate flags.

$gcc -c -fpic -o myobj.o mylib.c

-fpic: PIC stands for position indepent code. Such a code can be loaded at any location in the memory by the operating system. Dont get afraid by PIC, in a sense it's nothing but code in which all branch instructions are PC (Program Counter) relative.

Step 3: At this point our object is ready but not the .so. Let us get that done.

$gcc -shared -o libmy.so obj.o

-shared: This tells gcc to invoke linker and create a shared object out of the input file(s).

Step 4: Great! You have written a shared library and its name is libmy.so. What next? As usual after implementation the next phase is testing, let us test our shared lib i.e. can I call myprint from my hello world program. Write a hello world program like this -

* file: hello.c *
int main ()
{
myprint ("Hello world");
}

Compile it using gcc -

$gcc hello.c

linker will give a link error at this point something like symbol not resolved. Because there is no symbol myprint in std libs. Compile like this -

$gcc -lmy -L. hello.c

-l : Specify the library name. Just tell the name after lib e.g. here our lib name is "libmy.so" and hence "my".
-L: Specify the path where this library exists. I said . i.e. current dir.

Let us run it now -

$./a.out

Expect an error like this: library not found.
WHY? The loader tried to load "libmy.so" but could not find it in std lib dir PATH. Do this -

$echo $LD_LIBRARY_PATH

It will give you the path, where shared libraries should be searched for loading into the memory. So what we have to do is either copy the "libmy.so" file into any dir which is there in $LD_LIBRARY_PATH or include the path of our "libmy.so" in $LD_LIBRARY_PATH choice is yours. I will do the following for this small testing -

$LD_LIBRARY_PATH=. ./a.out

Hello World

This sets environment variable only for the command given next to the assignment.
That's it guys. I will try to come up with more on .so as I learn.
Please leave your comments if you find it helpful.