/Lib/ctypes/util.py

http://unladen-swallow.googlecode.com/ · Python · 241 lines · 180 code · 25 blank · 36 comment · 54 complexity · 0bab2412b6e9c7da8d6330397759f92c MD5 · raw file

  1. ######################################################################
  2. # This file should be kept compatible with Python 2.3, see PEP 291. #
  3. ######################################################################
  4. import sys, os
  5. # find_library(name) returns the pathname of a library, or None.
  6. if os.name == "nt":
  7. def _get_build_version():
  8. """Return the version of MSVC that was used to build Python.
  9. For Python 2.3 and up, the version number is included in
  10. sys.version. For earlier versions, assume the compiler is MSVC 6.
  11. """
  12. # This function was copied from Lib/distutils/msvccompiler.py
  13. prefix = "MSC v."
  14. i = sys.version.find(prefix)
  15. if i == -1:
  16. return 6
  17. i = i + len(prefix)
  18. s, rest = sys.version[i:].split(" ", 1)
  19. majorVersion = int(s[:-2]) - 6
  20. minorVersion = int(s[2:3]) / 10.0
  21. # I don't think paths are affected by minor version in version 6
  22. if majorVersion == 6:
  23. minorVersion = 0
  24. if majorVersion >= 6:
  25. return majorVersion + minorVersion
  26. # else we don't know what version of the compiler this is
  27. return None
  28. def find_msvcrt():
  29. """Return the name of the VC runtime dll"""
  30. version = _get_build_version()
  31. if version is None:
  32. # better be safe than sorry
  33. return None
  34. if version <= 6:
  35. clibname = 'msvcrt'
  36. else:
  37. clibname = 'msvcr%d' % (version * 10)
  38. # If python was built with in debug mode
  39. import imp
  40. if imp.get_suffixes()[0][0] == '_d.pyd':
  41. clibname += 'd'
  42. return clibname+'.dll'
  43. def find_library(name):
  44. if name in ('c', 'm'):
  45. return find_msvcrt()
  46. # See MSDN for the REAL search order.
  47. for directory in os.environ['PATH'].split(os.pathsep):
  48. fname = os.path.join(directory, name)
  49. if os.path.isfile(fname):
  50. return fname
  51. if fname.lower().endswith(".dll"):
  52. continue
  53. fname = fname + ".dll"
  54. if os.path.isfile(fname):
  55. return fname
  56. return None
  57. if os.name == "ce":
  58. # search path according to MSDN:
  59. # - absolute path specified by filename
  60. # - The .exe launch directory
  61. # - the Windows directory
  62. # - ROM dll files (where are they?)
  63. # - OEM specified search path: HKLM\Loader\SystemPath
  64. def find_library(name):
  65. return name
  66. if os.name == "posix" and sys.platform == "darwin":
  67. from ctypes.macholib.dyld import dyld_find as _dyld_find
  68. def find_library(name):
  69. possible = ['lib%s.dylib' % name,
  70. '%s.dylib' % name,
  71. '%s.framework/%s' % (name, name)]
  72. for name in possible:
  73. try:
  74. return _dyld_find(name)
  75. except ValueError:
  76. continue
  77. return None
  78. elif os.name == "posix":
  79. # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
  80. import re, tempfile, errno
  81. def _findLib_gcc(name):
  82. expr = r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)
  83. fdout, ccout = tempfile.mkstemp()
  84. os.close(fdout)
  85. cmd = 'if type gcc >/dev/null 2>&1; then CC=gcc; elif type cc >/dev/null 2>&1; then CC=cc;else exit 10; fi;' \
  86. '$CC -Wl,-t -o ' + ccout + ' 2>&1 -l' + name
  87. try:
  88. f = os.popen(cmd)
  89. trace = f.read()
  90. rv = f.close()
  91. finally:
  92. try:
  93. os.unlink(ccout)
  94. except OSError, e:
  95. if e.errno != errno.ENOENT:
  96. raise
  97. if rv == 10:
  98. raise OSError, 'gcc or cc command not found'
  99. res = re.search(expr, trace)
  100. if not res:
  101. return None
  102. return res.group(0)
  103. if sys.platform == "sunos5":
  104. # use /usr/ccs/bin/dump on solaris
  105. def _get_soname(f):
  106. if not f:
  107. return None
  108. cmd = "/usr/ccs/bin/dump -Lpv 2>/dev/null " + f
  109. res = re.search(r'\[.*\]\sSONAME\s+([^\s]+)', os.popen(cmd).read())
  110. if not res:
  111. return None
  112. return res.group(1)
  113. else:
  114. def _get_soname(f):
  115. # assuming GNU binutils / ELF
  116. if not f:
  117. return None
  118. cmd = 'if ! type objdump >/dev/null 2>&1; then exit 10; fi;' \
  119. "objdump -p -j .dynamic 2>/dev/null " + f
  120. f = os.popen(cmd)
  121. dump = f.read()
  122. rv = f.close()
  123. if rv == 10:
  124. raise OSError, 'objdump command not found'
  125. res = re.search(r'\sSONAME\s+([^\s]+)', os.popen(cmd).read())
  126. if not res:
  127. return None
  128. return res.group(1)
  129. if (sys.platform.startswith("freebsd")
  130. or sys.platform.startswith("openbsd")
  131. or sys.platform.startswith("dragonfly")):
  132. def _num_version(libname):
  133. # "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ]
  134. parts = libname.split(".")
  135. nums = []
  136. try:
  137. while parts:
  138. nums.insert(0, int(parts.pop()))
  139. except ValueError:
  140. pass
  141. return nums or [ sys.maxint ]
  142. def find_library(name):
  143. ename = re.escape(name)
  144. expr = r':-l%s\.\S+ => \S*/(lib%s\.\S+)' % (ename, ename)
  145. res = re.findall(expr,
  146. os.popen('/sbin/ldconfig -r 2>/dev/null').read())
  147. if not res:
  148. return _get_soname(_findLib_gcc(name))
  149. res.sort(cmp= lambda x,y: cmp(_num_version(x), _num_version(y)))
  150. return res[-1]
  151. else:
  152. def _findLib_ldconfig(name):
  153. # XXX assuming GLIBC's ldconfig (with option -p)
  154. expr = r'/[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)
  155. res = re.search(expr,
  156. os.popen('/sbin/ldconfig -p 2>/dev/null').read())
  157. if not res:
  158. # Hm, this works only for libs needed by the python executable.
  159. cmd = 'ldd %s 2>/dev/null' % sys.executable
  160. res = re.search(expr, os.popen(cmd).read())
  161. if not res:
  162. return None
  163. return res.group(0)
  164. def _findSoname_ldconfig(name):
  165. import struct
  166. if struct.calcsize('l') == 4:
  167. machine = os.uname()[4] + '-32'
  168. else:
  169. machine = os.uname()[4] + '-64'
  170. mach_map = {
  171. 'x86_64-64': 'libc6,x86-64',
  172. 'ppc64-64': 'libc6,64bit',
  173. 'sparc64-64': 'libc6,64bit',
  174. 's390x-64': 'libc6,64bit',
  175. 'ia64-64': 'libc6,IA-64',
  176. }
  177. abi_type = mach_map.get(machine, 'libc6')
  178. # XXX assuming GLIBC's ldconfig (with option -p)
  179. expr = r'(\S+)\s+\((%s(?:, OS ABI:[^\)]*)?)\)[^/]*(/[^\(\)\s]*lib%s\.[^\(\)\s]*)' \
  180. % (abi_type, re.escape(name))
  181. res = re.search(expr,
  182. os.popen('/sbin/ldconfig -p 2>/dev/null').read())
  183. if not res:
  184. return None
  185. return res.group(1)
  186. def find_library(name):
  187. return _findSoname_ldconfig(name) or _get_soname(_findLib_gcc(name))
  188. ################################################################
  189. # test code
  190. def test():
  191. from ctypes import cdll
  192. if os.name == "nt":
  193. print cdll.msvcrt
  194. print cdll.load("msvcrt")
  195. print find_library("msvcrt")
  196. if os.name == "posix":
  197. # find and load_version
  198. print find_library("m")
  199. print find_library("c")
  200. print find_library("bz2")
  201. # getattr
  202. ## print cdll.m
  203. ## print cdll.bz2
  204. # load
  205. if sys.platform == "darwin":
  206. print cdll.LoadLibrary("libm.dylib")
  207. print cdll.LoadLibrary("libcrypto.dylib")
  208. print cdll.LoadLibrary("libSystem.dylib")
  209. print cdll.LoadLibrary("System.framework/System")
  210. else:
  211. print cdll.LoadLibrary("libm.so")
  212. print cdll.LoadLibrary("libcrypt.so")
  213. print find_library("crypt")
  214. if __name__ == "__main__":
  215. test()