0

I have a large program that may be linked against some external libraries, but these are only needed for some specific functions. However, even if I don't use these functions, the external libraries are still required. Can I do something (preferably at compile or link time) so that the libraries are only required if the functionality they provide is requested?

Example:

hello.c

#include <stdio.h>
#include <unistd.h>
extern const char *myfunc();

main() {
  int z;
  char buf[32];
  z = gethostname(buf,sizeof buf);
  if (strcmp(buf,"#!#!#!#!#") == 0) {
    printf("%s\n", myfunc());
  } else {
    printf("%s\n", "No library used");
  }
  return 0;
}

shrobj.c:

const char *myfunc() {
  return "Hello World";
}

Compiled as:

$ gcc -fpic -c shrobj.c
$ gcc -shared -o libshared.so shrobj.o
$ gcc hello.c -lshared -L.
$ ./a.out 
./a.out: error while loading shared libraries: libshared.so: cannot open shared object file: No such file or directory

and my hostname is obviously not #!#!#!#!#:

$ LD_LIBRARY_PATH=. ./a.out 
No library used

So, what I want is being able to run "./a.out" without the library (which for whatever reason may be unavailable), as long as its function is not called.

I've seen that delayed loading can be obtained with dlopen() but, even though the above example is in C, most of my code is in fortran, and in particular the part that might call the functions in the library.

Jellby
  • 2,360
  • 3
  • 27
  • 56

1 Answers1

0

Linux can do this already through its kernel API; specifically, the dlopen(3) function. Look it up with man if you want the specifics.

Basically, you call dlopen with the name of the library to load and it returns a handle to the library, which you'll need to save for later.

void* lib = dlopen("./lib.so"); // this can be any path

To load a function from this library, you use the dlsym function, and you assign its return value to a function pointer which you can then call like any other function in your program (well, mostly).

int (*func)() = dlsym(lib, "thing");

When you're done, you need to tell the kernel that you're done with the library:

dlclose(lib)

I've omitted error checking here for the sake of brevity, but you'll need to do it in real code.

Doing it this way means that your program will not try to load the library unless it is needed, so if the required library or dependency isn't installed or is missing, your code can detect that and use something else instead. Your program - as long as it is written properly - will not crash at startup, though you will probably have to exit with an error if you depend on the library a lot and it can't be found.

SevenBits
  • 2,836
  • 1
  • 20
  • 33
  • Thanks for the details. How much of it is linux-specific? How would it work with fortran? – Jellby Jan 20 '15 at 20:35
  • @Jellby Sorry if I was unclear. This function is part of the GNU C library; it is not Linux specific. In fact, it also works on OS X and FreeBSD. – SevenBits Jan 21 '15 at 16:33
  • @Jellby I can't say if it will work with Fortran as I've never used Fortran. Sorry. – SevenBits Jan 21 '15 at 16:35