shlibs/dynload.c

This is shlibs/dynload.c (Listing 42-1, page 865), an example from the book, The Linux Programming Interface.

The source code file is copyright 2024, Michael Kerrisk, and is licensed under the GNU General Public License, version 3.

This page shows the "distribution" or "book" version of the file (why are there two versions?), or the differences between the two versions. You can switch between the views using the tabs below.

In the listing below, the names of Linux system calls and C library functions are hyperlinked to manual pages from the Linux man-pages project, and the names of functions implemented in the book are hyperlinked to the implementations of those functions.

  Cover of The Linux Programming Interface
+/* dynload.c
+
+   Usage: dynload library-path function-name
+
+   Demonstrate dynamic loading of libraries. The program loads the
+   named library and then executes the named function in that library.
+*/
 #include <dlfcn.h>
 #include "tlpi_hdr.h"
 
 int
 main(int argc, char *argv[])
 {
     void *libHandle;            /* Handle for shared library */
     void (*funcp)(void);        /* Pointer to function with no arguments */
     const char *err;
 
     if (argc != 3 || strcmp(argv[1], "--help") == 0)
         usageErr("%s lib-path func-name\n", argv[0]);
 
     /* Load the shared library and get a handle for later use */
 
     libHandle = dlopen(argv[1], RTLD_LAZY);
     if (libHandle == NULL)
         fatal("dlopen: %s", dlerror());
 
     /* Search library for symbol named in argv[2] */
 
     (void) dlerror();                           /* Clear dlerror() */
-    *(void **) (&funcp) = dlsym(libHandle, argv[2]);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+    funcp = (void (*)(void)) dlsym(libHandle, argv[2]);
+#pragma GCC diagnostic pop
+
+    /* In the book, instead of the preceding line, the code uses a
+       rather clumsy looking cast of the form:
+
+           *(void **) (&funcp) = dlsym(libHandle, argv[2]);
+
+       This was done because the ISO C standard does not require compilers
+       to allow casting of pointers to functions back and forth to 'void *'.
+       (See TLPI pages 863-864.) SUSv3 TC1 and SUSv4 accepted the ISO C
+       requirement and proposed the clumsy cast as the workaround. However,
+       the 2013 Technical Corrigendum to SUSv4 requires implementations
+       to support casts of the more natural form (now) used in the code
+       above. However, various current compilers (e.g., gcc with the
+       '-pedantic' flag) may still complain about such casts. Therefore,
+       we use a gcc pragma to disable the warning.
+
+       Note that this pragma is available only since gcc 4.6, released in
+       2010. If you are using an older compiler, the pragma will generate
+       an error. In that case, simply edit this program to remove the
+       lines above that begin with '#pragma".
+
+       See also the erratum note for page 864 at
+       http://www.man7.org/tlpi/errata/. */
+
     err = dlerror();
     if (err != NULL)
         fatal("dlsym: %s", err);
 
     /* Try calling the address returned by dlsym() as a function
        that takes no arguments */
 
     (*funcp)();
 
     dlclose(libHandle);                         /* Close the library */
 
     exit(EXIT_SUCCESS);
 }

Note that, in most cases, the programs rendered in these web pages are not free standing: you'll typically also need a few other source files (mostly in the lib/ subdirectory) as well. Generally, it's easier to just download the entire source tarball and build the programs with make(1). By hovering your mouse over the various hyperlinked include files and function calls above, you can see which other source files this file depends on.

Valid XHTML 1.1