Search code examples
linkershared-librariesdlopendynamic-loading.so

When to actually use dlopen()? Does dlopen() means dynamic loading?


I have gone through below link, through which I understood how to create and use shared library. https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html

Step 1: Compiling with Position Independent Code
$ gcc -c -Wall -Werror -fpic foo.c

Step 2: Creating a shared library from an object file
$ gcc -shared -o libfoo.so foo.o

Step 3: Linking with a shared library
$ gcc -L/home/username/foo -Wall -o test main.c -lfoo

Step 4: Making the library available at runtime
$ export LD_LIBRARY_PATH=/home/username/foo:$LD_LIBRARY_PATH
$ ./test
This is a shared library test...
Hello, I am a shared library

However, I have couple of questions:

  1. In the given link, there is no usage of dlopen(), which is required to open shared library. How this code is working without dlopen() calls?
  2. When to actually use dlopen()?
  3. Can I compile program without having .so file available (program has function calls to that shared library)?
  4. Does the dlopen() means dynamic loading and example in above link(step 3) means static loading? If Yes, then in case of dynamic loading, is there any difference in linking step(step 3)?

Solution

  • Dynamic Library

    When we link an application against a shared library, the linker leaves some stubs (unresolved symbols) to be filled at application loading time. These stubs need to be filled by a tool called, dynamic linker at run time or at application loading time.

    Loading of a shared library is of two types,

    1. Dynamically linked libraries

    Here a program is linked with the shared library and the kernel loads the library (in case it’s not in memory) upon execution. This is explained in mentioned link.

    1. Dynamically loaded libraries

    Useful for creating a "plug-in" architecture. As the name indicates, dynamic loading is about loading of library on demand and linked during execution. The program takes full control by calling functions with the library. This is done using dlopen(), dlsym(), dlclose(). The dlopen() function opens a library and prepares it for use. With this system call it is possible to open a shared library and use the functions from it, without having to link with it. Your program just starts, and when it finds out that it needs to use a function from a specific library, it calls dlopen() to open that library. If the library is not available on the system, the function returns NULL and it is up to you, the programmer, to handle that. You can let the program gracefully die.

    DL Example: This example loads the math library and prints the cosine of 2.0, and it checks for errors at every step (recommended):

    #include <stdlib.h>
    #include <stdio.h>
    #include <dlfcn.h>
    
    int main(int argc, char **argv) {
        void *handle;
        double (*cosine)(double);
        char *error;
    
        handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);
        if (!handle) {
            fputs (dlerror(), stderr);
            exit(1);
        }
    
        cosine = dlsym(handle, "cos");
        if ((error = dlerror()) != NULL)  {
            fputs(error, stderr);
            exit(1);
        }
    
        printf ("%f\n", (*cosine)(2.0));
        dlclose(handle);
    }
    

    Use -rdynamic while compiling DL source code.

    Ex. gcc -rdynamic -o progdl progdl.c -ldl