Search code examples
c++linuxqtdynamic-loadingqlibrary

QLibrary::load fails, but LD_LIBRARY_PATH just updated correctly before that, why?


I have a library (let's call it mydll.so) that is dependent to an external application, i.e. Matlab. To dynamically load mydll.so, I have written a code like this (Ubuntu, g++ 4.8.5, qt 5.12.6):

// update LD_LIBRARY_PATH with ALL required paths (Matlab, boost, etc.)
bool res = qputenv("LD_LIBRARY_PATH", required_path.toStdString().c_str());
assert(res);

// loading the dll
QLibrary my_dll;

my_dll.setFileName(dll_path);
if (!my_dll.load())
{
   std::cout << my_dll.errorString().toStdString() << std::endl;
}

The above code fails with this message:

Cannot load library /home/user/code/test/lnx_x64/debug/mydll.so: (libMatlabDataArray.so: cannot open shared object file: No such file or directory)

It is strange because the load() function is complaining about a library from Matlab, i.e. libMatlabDataArray.so that its path is already included in LD_LIBRARY_PATH. But, if I run ldd on the same environment, I have:

user@everest:~/code$ ldd /home/user/code/test/lnx_x64/debug/mydll.so
    linux-vdso.so.1 (0x00007ffcb4da2000)
    libMatlabDataArray.so => /usr/local/MATLAB/extern/bin/glnxa64/libMatlabDataArray.so (0x00007f6af95f2000)
    libMatlabEngine.so => /usr/local/MATLAB/extern/bin/glnxa64/libMatlabEngine.so (0x00007f6af93e7000)

That means the libMatlabDataArray.so can be found by ldd command and the contents of LD_LIBRARY_PATH is correct. Then what can be the reason behind this issue in my case?

Update 1: If I set the LD_LIBRARY_PATH before the application is started, everything works fine. What is the difference between setting the the LD_LIBRAARY_PATH before launching the application and inside it?


Solution

  • The problem is that you change the environment variable LD_LIBRARY_PATH from within the process. However the process still uses the "old" environment variables block with old values. As a result it cannot properly find the dependent libraries and eventually fails. Therefore your approach will not work. I would propose the following solutions:

    • Set the LD_LIBRARY_PATH variable before starting the process, so that the process can take the updated block into account,
    • Try to use QCoreApplication::setLibraryPaths() function to set the library search paths.