Question

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++).

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top