在Python中,ctypes.util.find_library
可用于以类似于编译器的方式定位库。在Mac OSX中,该函数返回完整路径名。但在linux中,只返回文件名。 (这是docs)
有没有办法在linux中获取完整路径?
答案 0 :(得分:2)
您可以使用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)
例如:
$ python test.py
libxml2.so.2
/usr/lib/libxml2.so.2
$
答案 1 :(得分:1)
find_library做这样的事情。为什么我们不应该这样做呢?
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