Sunday, November 11, 2012

Static and Dynamic Libraries in C in Linux

Hi All...!!!

I am writing this post as a explanation for the doubts raised by few of the readers of my blog. I will be discussing about Static and Dynamic libraries in C in Linux with a sample code.

Libraries are also known as "shared components" or "archive libraries" which groups together multiple compiled object code files into a single file known as a library. 

Typically C functions which can be shared by more than one application are broken out of the application's source code, compiled and bundled into a library. The C standard libraries are examples of shared components which can be linked with your code.

The benefit is that each and every object file need not be stated when linking because the developer can reference the individual library. This simplifies the multiple use and sharing of software components between applications. It also allows application vendors a way to simply release an API to interface with an application. 

Components which are large can be created for dynamic use, thus the library remain separate from the executable reducing it's size and thus disk space used. The library components are then called by various applications for use when needed.

There are two Linux C library types which can be created:

Static libraries: Library of object code which is linked with, and becomes part of the application.


Dynamically linked shared object libraries: There is only one form of this library but it can be used in two ways.

  • Dynamically linked at run time but statically aware. The libraries must be available during compile/link phase. The shared objects are not included into the executable component but are tied to the execution.
  • Dynamically loaded/unloaded and linked during execution (i.e. browser plug-in) using the dynamic linking loader system functions.

Library naming conventions:
  • Libraries are typically names with the prefix "lib", this is true for all C standard libraies
  • Static libraries are with extension (.a)
  • Dynamic or Shared libraries are with extension (.so)
Static libraries are loaded when the program is compiled and Dynamically-linked libraries are loaded at run time. Dynamic libraries save the RAM space as against the Static library because linking to static libraries includes the actual code for the library functions with the executable. DLL code is kept at one location and is shared among all the processes/application that uses the DLL.


Dynamic loading and un-loading of shared libraries in C in Linux

This is the other way of using Dynamic libraries by loading/unloading at runtime.

Please refer to my earlier posts for more explanation/understanding

Step1: Implement the library source. Let us assume there are two files namely one.c and two.c each implementing one function as follows
$ vim one.c

#include <stdio.h>
int myadd(int a, int b)
{
        return a+b;
}

$ vim two.c

#include <stdio.h>
int mymult(int a, int b)
{
       return a*b;
}

Step2: Compile the sources to generate relocatable.

Note: ‘.so’ is the extension for dynamic libraries.

$ gcc -c -fpic one.c 
        ( to create a relocatable one.o )
$ gcc -c -fpic two.c 
       ( to create a relocatable two.o ) 
$ gcc -shared -o libmyown.so one.o two.o
        ( libmyown.so is the name of the dynamic library to be created )
         - shared flag used to create a shared library 

Step3: Create the source file to dynamically load our share-library.

here funAddPtr and funMultPtr are the function pointer for myadd and mymult

Please refer to man-pages for dlopen, dlsym, dlclose 

$ vim test.c


#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main()
{
void *module;
int (*funAddPtr)(int,int);
int (*funMultPtr)(int,int);

char *error;

printf("Example : Dynamic loading/un-loading of shared library\n");


/* Load dynamically loaded library */
module = dlopen("./libmyown.so", RTLD_LAZY);
if (!module) {
fprintf(stderr, "Couldn't open libmine.so: %s\n", dlerror());
exit(1);
}

    funAddPtr = dlsym(module, "myadd");
    if ((error = dlerror()) != NULL)  {
        fprintf (stderr, "%s\n", error);
        exit(1);
    }

printf("Sum of 3,4 = %d\n", funAddPtr(3,4));


funMultPtr = dlsym(module, "mymult");
if ((error = dlerror()) != NULL)  {
        fprintf (stderr, "%s\n", error);
        exit(1);
    }
    
    printf("Product of 3,4 = %d\n", funMultPtr(3,4));

dlclose(module);

return 0;
}

Step4: Compile the source and run

$ gcc -rdynamic -o test test.c -ldl

$./test

Example : Dynamic loading/un-loading of shared library
Sum of 3,4 = 7
Product of 3,4 = 12