Solving C library call incompatibilities with the dynamic linking loader
While testing the latest dynamically-linked binary version of SCAMP on various Linux platforms, I discovered that the executable would sometimes exit with the error message:
This happens exclusively with older versions of the PLplot library, libplplotd, because of a change PLplot developers made to the API circa 2007. After this date, plimage() was replaced with c_plimage(). Although compatibility is maintained at compile time thanks to a
in the plplot.h include file, it is lost for dynamically-linked executables such as SCAMP. How then to make the program work with any version of the PLplot library? To my knowledge, there isn’t much that can be done at compile or link-time using the standard C library to solve this problem.
Fortunately, a POSIX-compliant solution exists. The dlopen(), dlclose(), and dlsym() functions allow respectively to open/close a dynamic library, and query symbol (function) pointers in it. The problem above can be solved by replacing calls to plimage() by (*myplimage)(), and setting the function pointer myplimage either to plimage or c_plimage depending on their availability. Here is a code example to replace a call to plimage(3.1416) (I simplified the arguments to plimage() for readability):
…
void (*myplimage)(double *dummy);
void *dl, *fptr;
dl = dlopen("libplplotd.so", RTLD_LAZY);
if ((fptr = dlsym(dl, "plimage")))
myplimage = fptr;
else
myplimage = dlsym(dl, "c_plimage");
(*myplimage)(3.1416);
dlclose(dl);
…
RTLD_LAZY is one of the flags available to control binding rules; see the dlopen() man page for more details.