| .\" -*- nroff -*- |
| .\" Copyright 1995 Yggdrasil Computing, Incorporated. |
| .\" written by Adam J. Richter (adam@yggdrasil.com), |
| .\" with typesetting help from Daniel Quinlan (quinlan@yggdrasil.com). |
| .\" |
| .\" This is free documentation; you can redistribute it and/or |
| .\" modify it under the terms of the GNU General Public License as |
| .\" published by the Free Software Foundation; either version 2 of |
| .\" the License, or (at your option) any later version. |
| .\" |
| .\" The GNU General Public License's references to "object code" |
| .\" and "executables" are to be interpreted as the output of any |
| .\" document formatting or typesetting system, including |
| .\" intermediate and printed output. |
| .\" |
| .\" This manual is distributed in the hope that it will be useful, |
| .\" but WITHOUT ANY WARRANTY; without even the implied warranty of |
| .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| .\" GNU General Public License for more details. |
| .\" |
| .\" You should have received a copy of the GNU General Public |
| .\" License along with this manual; if not, write to the Free |
| .\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, |
| .\" USA. |
| .\" |
| .TH DLOPEN 3 "16 May 1995" "Linux" "Linux Programmer's Manual" |
| .SH NAME |
| dlclose, dlerror, dlopen, dlsym \- Programming interface to dynamic linking loader. |
| .SH SYNOPSIS |
| .B #include <dlfcn.h> |
| .sp |
| .BI "void *dlopen (const char *" "filename" ", int " flag "); |
| .br |
| .BI "const char *dlerror(void);" |
| .br |
| .BI "void *dlsym(void *"handle ", char *"symbol ");" |
| .br |
| .BI "int dladdr(void *"address ", Dl_info *"dlip ");" |
| .br |
| .BI "int dlclose (void *"handle "); |
| .sp |
| Special symbols: |
| .BR "_init" ", " "_fini" ". " |
| .SH DESCRIPTION |
| .B dlopen |
| loads a dynamic library from the file named by the null terminated |
| string |
| .I filename |
| and returns an opaque "handle" for the dynamic library. |
| If |
| .I filename |
| is not an absolute path (i.e., it does not begin with a "/"), then the |
| file is searched for in the following locations: |
| .RS |
| .PP |
| A colon-separated list of directories in the user's |
| \fBLD_LIBRARY\fP path environment variable. |
| .PP |
| The list of libraries specified in \fI/etc/ld.so.cache\fP. |
| .PP |
| \fI/usr/lib\fP, followed by \fI/lib\fP. |
| .RE |
| .PP |
| If |
| .I filename |
| is a NULL pointer, then the returned handle is for the main program. |
| .PP |
| External references in the library are resolved using the libraries |
| in that library's dependency list and any other libraries previously |
| opened with the |
| .B RTLD_GLOBAL |
| flag. |
| If the executable was linked |
| with the flag "-rdynamic", then the global symbols in the executable |
| will also be used to resolve references in a dynamically loaded |
| library. |
| .PP |
| .I flag |
| must be either |
| .BR RTLD_LAZY , |
| meaning resolve undefined symbols as code from the dynamic library is |
| executed, or |
| .BR RTLD_NOW , |
| meaning resolve all undefined symbols before |
| .B dlopen |
| returns, and fail if this cannot be done. |
| Optionally, |
| .B RTLD_GLOBAL |
| may be or'ed with |
| .IR flag, |
| in which case the external symbols defined in the library will be |
| made available to subsequently loaded libraries. |
| .PP |
| If the library exports a routine named |
| .BR _init , |
| then that code is executed before dlopen returns. |
| If the same library is loaded twice with |
| .BR dlopen() , |
| the same file handle is returned. The dl library maintains link |
| counts for dynamic file handles, so a dynamic library is not |
| deallocated until |
| .B dlclose |
| has been called on it as many times as |
| .B dlopen |
| has succeeded on it. |
| .PP |
| If |
| .B dlopen |
| fails for any reason, it returns NULL. |
| A human readable string describing the most recent error that occurred |
| from any of the dl routines (dlopen, dlsym or dlclose) can be |
| extracted with |
| .BR dlerror() . |
| .B dlerror |
| returns NULL if no errors have occurred since initialization or since |
| it was last called. (Calling |
| .B dlerror() |
| twice consecutively, will always result in the second call returning |
| NULL.) |
| |
| .B dlsym |
| takes a "handle" of a dynamic library returned by dlopen and the null |
| terminated symbol name, returning the address where that symbol is |
| loaded. If the symbol is not found, |
| .B dlsym |
| returns NULL; however, the correct way to test for an error from |
| .B dlsym |
| is to save the result of |
| .B dlerror |
| into a variable, and then check if saved value is not NULL. |
| This is because the value of the symbol could actually be NULL. |
| It is also necessary to save the results of |
| .B dlerror |
| into a variable because if |
| .B dlerror |
| is called again, it will return NULL. |
| .PP |
| .B dladdr |
| returns information about the shared library containing the memory |
| location specified by |
| .IR address . |
| .B dladdr |
| returns zero on success and non-zero on error. |
| .PP |
| .B dlclose |
| decrements the reference count on the dynamic library handle |
| .IR handle . |
| If the reference count drops to zero and no other loaded libraries use |
| symbols in it, then the dynamic library is unloaded. If the dynamic |
| library exports a routine named |
| .BR _fini , |
| then that routine is called just before the library is unloaded. |
| .SH EXAMPLES |
| .B Load the math library, and print the cosine of 2.0: |
| .RS |
| .nf |
| .if t .ft CW |
| #include <dlfcn.h> |
| |
| int main(int argc, char **argv) { |
| void *handle = dlopen ("/lib/libm.so", RTLD_LAZY); |
| double (*cosine)(double) = dlsym(handle, "cos"); |
| printf ("%f\\n", (*cosine)(2.0)); |
| dlclose(handle); |
| } |
| .if t .ft P |
| .fi |
| .PP |
| If this program were in a file named "foo.c", you would build the program |
| with the following command: |
| .RS |
| .LP |
| gcc -rdynamic -o foo foo.c -ldl |
| .RE |
| .RE |
| .LP |
| .B Do the same thing, but check for errors at every step: |
| .RS |
| .nf |
| .if t .ft CW |
| #include <stdio.h> |
| #include <dlfcn.h> |
| |
| int main(int argc, char **argv) { |
| void *handle; |
| double (*cosine)(double); |
| char *error; |
| |
| handle = dlopen ("/lib/libm.so", 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); |
| } |
| .if t .ft P |
| .fi |
| .RE |
| .SH ACKNOWLEDGEMENTS |
| The dlopen interface standard comes from Solaris. |
| The Linux dlopen implementation was primarily written by |
| Eric Youngdale with help from Mitch D'Souza, David Engel, |
| Hongjiu Lu, Andreas Schwab and others. |
| The manual page was written by Adam Richter. |
| .SH SEE ALSO |
| .BR ld(1) , |
| .BR ld.so(8) , |
| .BR ldconfig(8) , |
| .BR ldd(1) , |
| .BR ld.so.info . |