C++ linux: dlopen can't find .so library

36,509

Solution 1

Read the dlopen(3) man page (e.g. by typing man dlopen in a terminal on your machine):

If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname. Otherwise, the dynamic linker searches for the library as follows (see ld.so(8) for further details):

   o   (ELF only) If the executable file for the calling program
       contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag,
       then the directories listed in the DT_RPATH tag are searched.

   o   If, at the time that the program was started, the environment
       variable LD_LIBRARY_PATH was defined to contain a colon-separated
       list of directories, then these are searched.  (As a security
       measure this variable is ignored for set-user-ID and set-group-ID
       programs.)

   o   (ELF only) If the executable file for the calling program
       contains a DT_RUNPATH tag, then the directories listed in that
       tag are searched.

   o   The cache file /etc/ld.so.cache (maintained by ldconfig(8)) is
       checked to see whether it contains an entry for filename.

   o   The directories /lib and /usr/lib are searched (in that order).

So you need to call dlopen("./libLibraryName.so", RTLD_NOW) -not just dlopen("libLibraryName.so", RTLD_NOW) which wants your plugin to be in your $LD_LIBRARY_PATH on in /usr/lib/ etc .... - or add . to your LD_LIBRARY_PATH (which I don't recommend for security reasons).

As Jhonnash answered you should use and display the result of dlerror when dlopen (or dlsym) fails:

  void* dlh = dlopen("./libLibraryName.so", RTLD_NOW);
  if (!dlh) 
    { fprintf(stderr, "dlopen failed: %s\n", dlerror()); 
      exit(EXIT_FAILURE); };

You might want to read some books like Advanced Linux Programming to get some knowledge about Linux system programming in general.

Solution 2

About the dlopen is defined; Dynamic library dlopen error can be checked. Undefined symbol error by this link.

Share:
36,509
NmdMystery
Author by

NmdMystery

Updated on July 09, 2022

Comments

  • NmdMystery
    NmdMystery almost 2 years

    Reworded Question (although it's been solved already):

    I've been having trouble using dlopen(3) to load a shared object library on linux. The library is part of a system of libraries built by me that are all loaded at runtime by a central executable. All of this is organized into a single workspace in Code::Blocks, where each project is given its own folder within a directory called Source, which is to be shipped with the program. The build directory of the executable is two directories backward from its own source code so that the exectuable and the Source folder are in the same directory, The libraries also build to the same directory as the executable, so naturally I pass the name of the library I'm trying to open as shown:

    int main(int argc, char** argv) {
        void* hLibrary = dlopen("libLibrary.so", RTLD_NOW | RTLD_GLOBAL);
        if(hLibrary == NULL) {
            fprintf(stderr, "%s\n", dlerror());
            return 1;
        }
    
        return 0;
    }
    

    This was working at one point when the build directory was the same as the source code, until I changed the directories of the source code around to the arrangement described above. The problem at this point is that dlerror() returns "Cannot open libLibrary.so: no such file or directory," even though the file clearly exists and is in the same directory as the executable. I then tried passing in "/libLibrary.so" instead, because according to the man page on dlopen(3), adding a / indicates a relative directory. This returned the same error.

    The solution to this was that a "./" was needed - where "." represents the working directory of the executable - and the working directory needed to be changed in Code::Blocks to where the executable was to be built. The following works perfectly:

    void* hLibrary = dlopen("./libLibrary.so", RTLD_NOW | RTLD_GLOBAL);
    

    This doesn't really show the full solution, but the following is basically the equivalent of what I'm doing:

    void* hLibrary = dlopen("./../../libLibrary.so", RTLD_NOW | RTLD_GLOBAL);
    

    Hopefully this explains the situation a little better.

  • NmdMystery
    NmdMystery almost 11 years
    I actually read that page before asking this question - the thing that got me was "relative or absolute" (they're like the opposite... which one is it?) and nowhere did it mention the "." I've been programming on windows most of the time, so I don't really know the difference between the plain name, the / before the name, and the ./ before the name. That fixed it though, thanks.
  • NmdMystery
    NmdMystery almost 11 years
    One thing though - how come dlopen found it before when I had no "./" before the name at all? It found both the library and its symbols just fine, which threw me off. (Also I figured out that the "." is the working directory, I just never needed to use it on Windows since it did it for me)
  • Basile Starynkevitch
    Basile Starynkevitch almost 11 years
    Linux is not Windows, but a Unix system. So, don't think using Windows habits.
  • NmdMystery
    NmdMystery almost 11 years
    Okay now it's giving me the same error as before. I double checked everything - the library is in the same directory as the executable, I have ./ in front of the name, and the name itself has no typos... I have it building two directories backward from the source, and the working directory is set up as "." Does "." mean the source directory, or the exec?
  • NmdMystery
    NmdMystery almost 11 years
    It turns out it was the execution working directory that was causing this @_@ I read a bit of the book you posted, though, and I'm taking some of the advice.