Project: Algorithms - Code Sharing
September 05, 2010, 06:54:29 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: I uploaded an updated beta version on the main page (http:\\alsabawi.com) with bug fixes only.  Also check out the video on YouTube -- not so bad!!
 
   Home   Help Search Login Register  
Pages: [1]   Go Down
  Print  
Author Topic: Dynamic shared library loading  (Read 523 times)
Seedhom
Administrator
Newbie
*****

Karma: +0/-0
Posts: 4



View Profile WWW
« on: November 01, 2009, 07:14:17 PM »

Once you create a set of functions that you like to reuse in multiple programs, you typically build them into a library.  The norm in Linux now has moved away from Static libraries (*.a) and more towards Shared Libraries (*.so).  Shared libraries can either be linked-in at compile time from a specific location on the system using -l and -L flags or can be loaded dynamically while the program is executing.  There are advantages and disadvantages for each of those 2 cases.  However, without going into depth about this, let me describe a case where dynamic loading of a shared library is most relevant.

Assume I am writing a server with the purpose to serve applications to users.  A typical case is when the user runs a client front-end application from which he makes requests to the server to execute other applications on the server side.  The requested applications has to be available to the server in the form of a loadable objects.  These loadable objects or shared libraries do not have to be predefined to the server before it starts, nor does the server need to know what they do once they are loaded.  All the server needs to know is where these libraries are in its file system and the name of the function the user needs to call.      

The example I am going to show here is not as elaborate as an application server, but it will show the technique fully.

The Shared Library

Start with the shared library I want to create with a trivial code:
Code:
#include <stdio.h>

int main(int argv, char *argc[])
{
printf("Hello World - I am loaded\n");
}
    Let us save this file as a C++ file just for kicks and call it
myloadingtest.cpp
To compile the above code as a shared library, we will do this in 2 steps:

  • (1) Compile using the -fPIC flag :
This will generate a position-independent code (PIC) so the OS dynamic loader can position it as it sees fit. Here is the compile line
[/list]
Code:
g++ -fPIC -c myloadingtest.cpp

  • (2) Generate the shared library from the object we just created:
We will need the -shared flag to tell that to the compiler. I am going to name the lib libmyloadingtest.so.  Here is the line:
Code:
g++ -shared  -o libmyloadingtest.so myloadingtest.o

    Now we have a shared library with only one entry: main(int, char **) in it.

    Now for the loading application (or server)...

    Shared Library Loader:
    Let me jump right away into the code:
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <dlfcn.h>

    int main(int argc, char *argv[])
    {
            void *handle;          // Pointer to the library location
            int (*mymain)(void);   // Pointer to point to the function in the lib to execute
            char *error;           // Pointer to the error that maybe returned by the dlerror() call

            // load the shared lib using Run Time Loader lazy mode
            handle = dlopen ("./mydynlibs/libmyloadingtest.so", RTLD_LAZY);
            if (!handle)
            {
                printf("This is an error in loading \n");
                exit(1);
            }
            printf("Library loaded successfully. Finding the function we need ..\n");

            // Resolve the function call ..
            mymain = (int (*)())dlsym(handle, "main");
            if ((error = dlerror()) != NULL)  
            {
                printf("Error: I did NOT find the symbol 'main' \n");
                exit(1);
            }
            printf("Success: Symbol 'main' was found. Calling it now ..\n");
            
                  
            mymain(); // Call the function entry in the library
            
            dlclose(handle);
        }

    Save the above code as file a C++ file dynamic_libload.cpp
    To compile, use this line
    Code:
    g++ -g  dynamic_libload.cpp -o dynamic_libload -ldl

    That is it!!

    Now a couple of points:
    There are only 2 calls needed to load a shared library dynamically:
    Code:
    void *handle = dlopen ("/path/to/lib/mylibname.so", RTLD_LAZY);
    ...
    dlclose(handle);

    And 2 calls are needed for each function symbol you need to point to:
    Code:
    myfunc_ptr = (<type> (*)())dlsym(handle, "function_name");
    // if myfunc_ptr turns NULL, then call
    error = dlerror()

    Another note to make about the option used in dlopen() call:  You can either use RTLD_LAZY or RTLD_NOW.  The first is the LAZY option which allows the loader to bind the library IF and only WHEN a function call is made to one of the library functions. The NOW option forces the loader to bind and resolve all the symbols in the shared library before the dlopen() returns. That could be a waste of time if for some reason the program decides not to call any of its functions.


    - Al Sabawi (Seedhom)
      Nov. 2, 2009
    « Last Edit: November 01, 2009, 07:48:57 PM by Seedhom » Logged

    ----------------------------
    Al Sabawi
    Pages: [1]   Go Up
      Print  
     
    Jump to:  

    Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!