Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
By Seedhom at 2009-11-03 04:39
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("Hey 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
Code:
g++ -fPIC -c myloadingtest.cpp
(2) Generate the shared library from the object we just created:[/li] 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:
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
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.
I only got as far as the second paragraph there before seeing something I think is a wrong enough direction that it deserves correction:
Quote:
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.
I can think of almost unlimited reasons why that should be done as separate processes launched by the server, and almost no reasons why you would consider doing it via .so files loaded into the server process address space.
I know it may be hard to think of an example that is realistic while still being simple enough to work through. But this choice of example gets the whole article off to a bad start.
Edit: Now I read the whole page there. That paragraph I complained about just distracts the reader and may cause some readers to go away before reading the useful parts. It doesn't really introduce what follows.
I don't think you even need that kind of ("what is it for") introduction to what follows. The example stands better alone without the lame introduction. If you do need an introduction, it should be a more reasonable one.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
I know it may be hard to think of an example that is realistic while still being simple enough to work through. But this choice of example gets the whole article off to a bad start.
Edit: Now I read the whole page there. That paragraph I complained about just distracts the reader and may cause some readers to go away before reading the useful parts. It doesn't really introduce what follows.
I don't think you even need that kind of ("what is it for") introduction to what follows. The example stands better alone without the lame introduction. If you do need an introduction, it should be a more reasonable one.