6

I need to check if a dynamic library is present, so that later I can safely call functions that use this library.

Is there a multiplatform way to check this? I am targeting MS Windows 7 (VC++11) and Linux (g++).

Parobay
  • 2,549
  • 3
  • 24
  • 36
  • LoadLibrary calls should fail, then you can know. Also with dynamic loading you get the function pointer from the dll and if the pointer is null then the platform doesn't support that function on that platform.What is the problem? – Abhijit-K Apr 10 '13 at 12:10
  • If the library fails to load, then my app crashes - i'd like to avoid that. The case is that I use some libraries (linked statically) that expect their runtime helper dynamic-libaries. – Parobay Apr 10 '13 at 12:17
  • For POSIX variants (like Linux and Mac OSX) look up [`dlopen`](http://pubs.opengroup.org/onlinepubs/009695399/functions/dlopen.html) and [`dlsym`](http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html). There are no cross-platform libraries that I know of, but it's simple and you can use very similar code to check for both Windows a Linux (same layout, just different functions really). – Some programmer dude Apr 10 '13 at 12:18
  • @JoachimPileborg what you are writing is exactly what I need! Could you describe this in an answer? – Parobay Apr 10 '13 at 12:22

2 Answers2

4

To dynamically "use" a function from a shared library requires that the library isn't part of the executable file, so you will need to write code to load the library and then use the function. There may well be ways to to do that in a portable fashion, but I'm not aware of any code available to do that.

It isn't very hard code to write. As "steps", it involves the following:

  1. Load the library given a name of a file (e.g. "xx", which is then translated to "xx.so" or "xx.dll" in the architecture specific code).
  2. Find a function based on either index ("function number 1") or name ("function blah"), and return the address.
  3. Repeat step 2 for all relevant functions.
  4. When no longer needing the library, close it with the handle provided.

If step 1 fails, then your library isn't present (or otherwise "not going to work"), so you can't call functions in it...

Clearly, there are many ways to design an interface to provide this type of functionality, and exactly how you go about that would depend on what your actual problem setting is.

Edit:

To clarify the difference between using a DLL directly, and using one using dynamic loading from the code:

Imagine that this is our "shared.h", which defines the functions for the shared library (There is probably some declspec(...) or exportsymbol or other such stuff in a real header, but I'll completely ignore that for now).

 int func1();
 char *func2(int x);

In a piece of code that directly uses the DLL, you'd just do:

 #include <shared.h>

 int main()
 {
     int x = func1();
     char *str = func2(42);

     cout << "x=" << x << " str=" << str << endl;
     return 0;
 }

Pretty straight forward, right?

When we use a shared library that is dynamically loaded by the code, it gets a fair bit more complex:

 #include <shared.h>

 typedef int (*ptrfunc1)();
 typedef char * (*ptrfunc2)(int x);

 int main()
 {
     SOMETYPE handle = loadlibrary("shared");
     if (handle == ERROR_INDICATOR)
     {
         cerr << "Error: Couldn't load shared library 'shared'";
         return 1;
     }
     ptrfunc1 pf1 = reinterpret_cast<ptrfunc1>(findfunc("func1"));
     ptrfunc2 pf2 = reinterpret_cast<ptrfunc2>(findfunc("func2"));

     int x = pf1();
     char *str = pf2(42);

     cout << "x=" << x << " str=" << str << endl;
     return 0;
 }

As you can see, the code suddenly got a lot more "messy". Never mind what hoops you have to jump through to find the constructor for a QObject, or worse, inherit from a QObject. In other words, if you are using Qt in your code, you are probably stuck with linking directly to "qt.lib" and your application WILL crash if a Qt environment isn't installed on the machine.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • Please note: I use eg. Qt functions from qt.lib (assume such a lib exists), and those functions themselves load a DLL. If they fail, my entire app fails. So I want to prevent this by manually checking if the DLL is present before they attempt to load it. Do you understand? – Parobay Apr 10 '13 at 12:30
  • Yes, and the only way to achieve that is to not link `qt.lib` to your application in the first, place, and then use code that you've written to check that you can load `qt.dll`, and then use it. But it will be a pretty nasty task to do for qt, since it's not got one simple interface. It's a whole raft of functions. And the whole point of qt is to make code portable and compile the same on multiple platforms. It would be a much better option to build an installer that checks if and/or makes sure `qt`is installed durign the installation of your application. – Mats Petersson Apr 10 '13 at 12:35
  • The point I'm making is that if you DO link with `qt.lib`, the system loader will automatically try to load `qt.dll` or `qt.so` when the application is started - if the shared library isn't there, it will fail the load of the executable file. This is part of how executables and their constituent shared libraries are loaded in a normal system. You can't change that, unless you stop using the `qt.lib`, which in turn means that you can't just use Qt functions in your code. You have to call them through an interface that checks if they are available or not, and if not, does something else. – Mats Petersson Apr 10 '13 at 12:39
  • Are you sure? If I link with `qt.lib` and dont use any of functions there declared - some magic loading of `qt.dll` will occur? how come, where does the information about requirements come from.. Dynamic libraries are dynamic because they are loaded at runtime, so why would system loader load the dll. **Short:** are talking in general (that ALL libs/dlls behave this way), or just presenting one possibiity of library/dll design? – Parobay Apr 10 '13 at 18:37
  • Yes, I'm 100% sure - although if you don't use ANY function from the library, it may not get linked in. However, what is the point of linking to a library that isn't being used in the executable? And I don't mean "hasn't been called at this point" - because DLL's are loaded [at least initialized] at the point of loading the executable. The only way to NOT have the effect of "fail if the library is not there" is to have not one single piece of code directly referring anything in qt.lib, and then using the library via `LoadLibrary` or `dlopen` and the respective functions to find each function. – Mats Petersson Apr 10 '13 at 22:17
  • Thank you, this is **much clearer** now. Does the second snippet (the one including `shared.h`) depend only on the header? In that case, how does the system know what DLL to load? /doesn't `shared.cpp` (impl of `shared.h`) load the library the way you showed in the 3rd snippet? – Parobay Apr 11 '13 at 19:02
  • No, it knows which DLL to load from the `"shared"` as an argument to `loadlibrary` - that function will add the correct extension `".dll"` or `".so"` depending on which OS you're using. "shared.cpp" will be inside the "shared.so" or "shared.dll". But you need to name it in your code, as there is no automatic loading of it. But your real problem is that you won't be able to use C++ classes with this method, because the compiler will want to know what member functions to call. If they have ALL their member functions virtual, and you can find it's constructor from its name, possibly. Not easy! – Mats Petersson Apr 11 '13 at 21:30
1

LoadLibrary calls should fail, then you can know if the dynamic library is present or not. Also with dynamic loading you get the function pointer from the dynamic library and if the pointer is null then the platform doesn't support that function on that platform.

On windows you have LoadLibrary API to load a dynamic lib. And GetProcAddress API to look up the desired function in that lib. If GetProcAddress returns NULL for that particular function that you are looking for that functionality is not present for that platform. You can log then and decide fallback.

Abhijit-K
  • 3,569
  • 1
  • 23
  • 31