In C++, is it possible to load a shared library at execution time?
I want the user to choose which shared library to be loaded at runtime, without recompiling the whole program.
dlopen()
is a solution for C, but my program is written is C++/Qt, and the symbol to extract are Qt-style class, is there a more "c++" way to do that.
Yes it's possible to do what you're describing on most operating systems, but how you do it is dependent on the system and regardless of the system it's definitely a bit more work on your end to make it happen.
The general steps are:
For example, in pseudo-code (read: this won't compile!) on a *nix type system, lets assume your shared library has this in it:
Assume this is in a library called libmyFunction.so. Your main application could, for example:
If you need to do this on Windows, the concept is the same but the function calls are different.
You can do it in Qt using
QLibrary
in two ways. The following example calls a function from a shared library at runtime in two different ways:The code for the shared library is as follows:
If the target library itself, or at least its specification, is under your control, then you shouldn't be using
QLibrary
- use the Qt plugin system instead. It doesn't require the call-via-pointer gymnastics otherwise needed.If you insist on using a
dlopen
-like mechanism, there is nothing C-specific aboutQLibrary
. The obvious limitation is that the library that you're trying to open must have been compiled with a C++ compiler that's ABI-compatible to the one you use to compile your own code. On Windows that really means using the same MSVC version.Apart from that, you'll have to look up the mangled version of the symbol. Once you've done that, you can call the symbol using a function/method pointer that matches it. This won't work on constructors/destructors, by design. If you wish to create new instances of objects, you'll need a static factory method provided by the library.
If the library doesn't provide factory methods, you can implement a shim library that links to the target library by a generic name and does provide factory methods. You'll still need to call individual methods by function/method pointers.
LD_LIBRARY_PATH
environment variable.LD_LIBRARY_PATH
.LD_LIBRARY_PATH
.Of course, you must have the header file for whatever interface the library exposes. It can't be, generally, reconstructed given just a dynamic library file - primarily because the mangled symbols don't have full structural information for the used types. For example, even if you can find a constructor for a given class, you won't know how big is the class instance (its
sizeof
).