I have gone through the Shared libraries with GCC on Linux documentation to understand how to create and use shared library.
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 a couple of questions:
dlopen()
, which is required to open shared library. How is this code working without dlopen()
calls?dlopen()
?dlopen()
means dynamic loading and example in above link(step 3) means static loading? If Yes, then in the case of dynamic loading, is there any difference in the linking step(step 3)?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:
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.
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