Вопрос

In Python, ctypes.util.find_library can be used to locate a library in a way similar to what the compiler does. In Mac OSX, the function returns a full pathname. But in linux, only the filename is returned. (Here are the docs )

Is there a way to obtain the fullpath also in linux?

Это было полезно?

Решение

You can load the library and the iterate over the loaded libraries using dl_iterate_phdr:

#!python
from ctypes import *
from ctypes.util import find_library

# this struct will be passed as a ponter,
# so we don't have to worry about the right layout
class dl_phdr_info(Structure):
  _fields_ = [
    ('padding0', c_void_p), # ignore it
    ('dlpi_name', c_char_p),
                            # ignore the reset
  ]


# call back function, I changed c_void_p to c_char_p
callback_t = CFUNCTYPE(c_int,
                       POINTER(dl_phdr_info), 
                       POINTER(c_size_t), c_char_p)

dl_iterate_phdr = CDLL('libc.so.6').dl_iterate_phdr
# I changed c_void_p to c_char_p
dl_iterate_phdr.argtypes = [callback_t, c_char_p]
dl_iterate_phdr.restype = c_int


def callback(info, size, data):
  # simple search
  if data in info.contents.dlpi_name:
    print(info.contents.dlpi_name)
  return 0

if __name__ == '__main__':
  # the target lib we want to find
  target_lib = find_library('xml2')
  print(target_lib)
  # load it
  lib = CDLL(target_lib)
  # iterate over the loaded libs
  dl_iterate_phdr(callback_t(callback), target_lib)

for example:

$ python test.py 
libxml2.so.2
/usr/lib/libxml2.so.2
$ 

Другие советы

find_library in Linux do things like this. Why we should not make it too?

import struct
def myfind(name):
    # see ctypes.find_library code
    uname = os.uname()[4]
    if uname.startswith("arm"):
        uname = "arm"
    if struct.calcsize('l') == 4:
        machine = uname + '-32'
    else:
        machine = uname + '-64'
    mach_map = {
        'x86_64-64': 'libc6,x86-64',
        'ppc64-64': 'libc6,64bit',
        'sparc64-64': 'libc6,64bit',
        's390x-64': 'libc6,64bit',
        'ia64-64': 'libc6,IA-64',
        'arm-32': 'libc6(,hard-float)?',
        }
    abi_type = mach_map.get(machine, 'libc6')
    # Note, we search libXXX.so.XXX, not just libXXX.so (!)
    expr = re.compile(r'^\s+lib%s\.so.[^\s]+\s+\(%s.*=>\s+(.*)$' % (re.escape(name), abi_type))
    p = subprocess.Popen(['ldconfig', '-N', '-p'], stdout=subprocess.PIPE)
    result = None
    for line in p.stdout:
        res = expr.match(line)
        if res is None:
            continue
        if result is not None:
            raise RuntimeError('Duplicate library found for %s' % name)
        result = res.group(1)
    if p.wait():
        raise RuntimeError('"ldconfig -p" failed')
    if result is None:
        raise RuntimeError('Library %s not found' % name)
    return result
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top