tags:

views:

166

answers:

3

C++ How to get a filename (and path) of the executing .so module in Unix?

Something similar to GetModuleFileName on Windows.

+2  A: 

Unfortunately, there is no way to do that using UNIX or POSIX. If you need to use it to look up some sort of data, you should use the $PATH environment variable and search for the data in a path that is relative to each entry in $PATH. For example, it is not uncommon to store binaries in "installdir/bin" for some installation directory "installdir" and to store the associated data in "installdir/share/name_of_program" for some installation directory and some program named "name_of_program". If that is the case, then looking at "../share/name_of_program/name_of_resource_file" relative to each entry in getenv("PATH") is a good way of searching for resources. Another thing you could do is allow the necessary information to be provided on the commandline or in some configuration file, and only perform the search if needed as a fallback option.

Edit
Now that you've stated your rationale for this, I would advise you to simply use the QSettings class from Qt for your configuration information, as it uses the preferred native mechanism for each platform (the registry on Windows, a PLIST file on Mac OS X, the Gnome GConf database on Linux). You may want to take a look at my C++ Project Template as it uses Qt to do just this, and it provides simple commandline options to easily tweak the configuration settings ("--prefset", "--prefget", and "--preflist" manipulate QSettings).

That said, if you absolutely must use an XML configuration file of your own instead of using the preferred native mechanism, I strongly advise you to place the system-wide configuration in "installdir/etc" while placing your library in "installdir/lib" for some installation directory "installdir", as that is the typical place for configuration files on UNIX systems, and "installdir/lib" should ONLY be used for library files, not for configuration files and other errata. I suggest you place a user-specific version of the configuration file in "$XDG_CONFIG_HOME" (if it is defined) or in "$HOME/.config" (where "$HOME" is the user's home folder).

When searching for the system-wide configuration file, I would recommend that you search within $XDG_CONFIG_DIRS if it is defined; if it isn't defined, then falling back to "/etc/xdg" or searching for "../etc/name_of_your_program.conf.xml" relative to "$PATH" and possibly also relative to the "$LD_LIBRARY_PATH", "$DYLD_LIBRARY_PATH", "$DYLD_FALLBACK_LIBRARY_PATH"), the contents of "/etc/ld.so.conf" if it exists, and the contents of "/etc/ld.so.conf.d/*.conf" if those files exist, halting your search as soon as you encounter the first valid such configuration file would be a sensible approach.

Credit goes to Roger for pointing out the XDG Basedir Spec and for his excellent constructive criticisms.

Michael Aaron Safyan
@Roger, thanks again. You are right again. Maybe you should consider writing a full answer... you'd probably do a better job, and I'd upvote you. In any case, your constructive criticisms are quite helpful. Thank you.
Michael Aaron Safyan
You're welcome, but I can't answer as, even though it's what he really wants, it doesn't answer what he actually asked. (@Steve: You're welcome to change the question to "How do I find configuration for my library/program?" though.. :P)
Roger Pate
A: 

Possible solutions:

  • You can read the /proc/{PID}/mmap file for the list of shared libraries. Where {PID} is the process pid (you can get it using getpid()).
  • Call the command line tool ldd for the program binary file (stored in argv[0]).
  • If you write a solution from scratch take a look of ldd commands source code from uClibc how to get the list of shared libs from an elf binary.
zoli2k
+2  A: 

Although it is not a POSIX standard interface, the dladdr() function is available on many systems including Linux, Solaris, Darwin/Mac OS X, FreeBSD, HP-UX, IRIX, and AIX. This function takes an address, which could be a pointer to a static function within the module for example (if cast to void *), and fills in a Dl_info structure with information including the path name of the shared object containing that address (in the dli_fname member).

mark4o
If I could still vote, I'd give a +1 for answering original question.
Michael Aaron Safyan
Now that I can vote, +1.
Michael Aaron Safyan
BTW found answer on SO (was asked 5 months ago): http://stackoverflow.com/questions/1681060/library-path-when-dynamically-loaded
Steve