Get absolute path of shared library in Python
Question: Let's say I wanted to use libc in Python. This can be easily done by

    
    
    from ctypes import CDLL
    from ctypes.util import find_library
    
    libc_path = find_library('c')
    libc = CDLL(libc_path)
    

Now, I know I could use ldconfig to get libc's abspath, but is there a way to
acquire it from the CDLL object? Is there something that can be done with its
`_handle`?

_Update_ : Ok.

    
    
    libdl = find_library('dl')
    RTLD_DI_LINKMAP = 2
    //libdl.dlinfo(libc._handle, RTLD_DI_LINKMAP, ???)
    

I need to redefine the `link_map` struct then?!


Answer: A handle in this context is basically a reference to the memory mapped library
file.

However there are existing ways to achieve what what you want with the help of
OS functions.

**windows:** Windows provides an API for this purpose called
`GetModuleFileName`. Some example of usage is already
[here](http://stackoverflow.com/questions/11007896/how-can-i-search-and-get-
the-directory-of-a-dll-file-in-python).

**linux:** There is existing a `dlinfo` function for this purpose, see
[here](http://man7.org/linux/man-pages/man3/dlinfo.3.html).

* * *

I played around with ctypes and here is my solution for linux based Systems. I
have zero knowledge of ctypes so far, if there are any suggestions for
improvement I appreciate them.

    
    
    from ctypes import *
    from ctypes.util import find_library
    
    #linkmap structure, we only need the second entry
    class LINKMAP(Structure):
        _fields_ = [
            ("l_addr", c_void_p),
            ("l_name", c_char_p)
        ]
    
    libc = CDLL(find_library('c'))
    libdl = CDLL(find_library('dl'))
    
    dlinfo = libdl.dlinfo
    dlinfo.argtypes  = c_void_p, c_int, c_void_p
    dlinfo.restype = c_int
    
    #gets typecasted later, I dont know how to create a ctypes struct pointer instance
    lmptr = c_void_p()
    
    #2 equals RTLD_DI_LINKMAP, pass pointer by reference
    dlinfo(libc._handle, 2, byref(lmptr))
    
    #typecast to a linkmap pointer and retrieve the name.
    abspath = cast(lmptr, POINTER(LINKMAP)).contents.l_name
    
    print(abspath)
    

