Dynamic Loading

This week, I will present the dl library and discuss dynamic loading

concepts. In essence, dynamic loading consists of opening a library,

searching for one or more symbols (which can refer to functions,

variables, arrays, etc...), using the retrieved symbols, and closing

the library. All of the functions and data types pertaining to dynamic

loading are declared in the header

. The dl Functions The dlerror() function reports the most recent error that occurred with any of the remaining dl functions. I will discuss the other dl functions shortly. The dlerror() function's prototype is as follows: const char * dlerror(void); dlerror() returns a string describing the error that occurred. If no error occurred, then it returns NULL. Remember that this function clears the error after it returns, so you must store the result if you intend to use it later. The dlopen() function opens a library and returns a matching handle. A library is a file of compiled code modules. Here is an example of the dlopen() function: void * dlopen(const char * filename, int flags) Typically, you pass an absolute pathname (i.e., a file beginning with a slash) as the filename but in this case, dlopen() doesn't need to search for the library. However, if you pass a simple filename, then the function looks for the library in the following places until it locates the specified library file: 1) A set of directories specified in the LD_ELF_LIBRARY_PATH environment variable. If this variable isn't defined, the directories listed in LD_LIBRARY_PATH are searched. 2) The libraries listed in the /etc/ld.so.cache file. 3) /usr/lib 4) /lib dlopen() returns NULL if it fails to open the specified library. Two types of symbol resolution exist: lazy and immediate. A lazy resolution means that symbol resolution is performed on demand. Lazy resolution is useful when you need to load a small portion of a huge library efficiently. By contrast, immediate resolution resolves all the library's unresolved symbols at once. Immediate resolution is useful when the library is small and for debugging purposes. dlopen()'s second argument indicates the resolution type: RTLD_LAZY and RTLD_NOW, for lazy and immediate resolution, respectively. You may combine either of these constants with the RTLD_GLOBAL to export symbols to other modules. For the symbol lookup process, use the dlsym() function: void* dlsym(void * libhandle, char * symbol); libhandle is a value returned from a previous dlopen() call. The second argument represents the function or variable's name that you want to retrieve. If the symbol was found, then dlsym() returns its address (you have to explicitly cast the return value to the desired type). Otherwise, dlsym() returns NULL. Note, however, that a NULL value can also be a valid address of a symbol, an initialized pointer for example. Therefore, if the sought-after symbol may have a NULL value, you have to call dlerror() after calling dlsym() to check whether the retrieval was successful. Calling dlclose() closes a library. It has the following prototype: void * dlclose(void * libhandle); Next week, I will continue this discussion and provide code examples showing how to load libraries dynamically.
What’s wrong? The new clean desk test
Join the discussion
Be the first to comment on this article. Our Commenting Policies