1 ###################################################################### 2 # This file should be kept compatible with Python 2.3, see PEP 291. # 3 ###################################################################### 4 import sys, os 5 6 # find_library(name) returns the pathname of a library, or None. 7 if os.name == "nt": 8 9 def _get_build_version(): 10 #*********************************************************** 11 # NOTE: As example for GCC(mingw) build sys.version return: 12 # '2.7a0 (trunk:<REVISION>M, <DATE>, <TIME>) \n[GCC 3.4.5 (mingw special)]' 13 # '2.7a0 (trunk:<REVISION>M, <DATE>, <TIME>) \n[GCC 4.4.0]' 14 #*********************************************************** 15 """Return the version of MSVC that was used to build Python. 16 17 For Python 2.3 and up, the version number is included in 18 sys.version. For earlier versions, assume the compiler is MSVC 6. 19 """ 20 # This function was copied from Lib/distutils/msvccompiler.py 21 prefix = "MSC v." 22 i = sys.version.find(prefix) 23 if i == -1: 24 return 6 25 i = i + len(prefix) 26 s, rest = sys.version[i:].split(" ", 1) 27 majorVersion = int(s[:-2]) - 6 28 minorVersion = int(s[2:3]) / 10.0 29 # I don't think paths are affected by minor version in version 6 30 if majorVersion == 6: 31 minorVersion = 0 32 if majorVersion >= 6: 33 return majorVersion + minorVersion 34 # else we don't know what version of the compiler this is 35 return None 36 37 def find_msvcrt(): 38 #************************************************************ 39 # FIXME: For GCC(mingw) runtime don't depend from compiler 40 # version ;). We may use -D__MSVCRT_VERSION__ to detect which 41 # verion is requested by user, but the name of the library 42 # to be default. 43 # As example WXP is with version 7.0 of msvcrt.dll. 44 # Anyway since _get_build_version return 6 in most(standard) 45 # cases this method will return msvcrt{d}. May be not so bad. 46 #************************************************************ 47 """Return the name of the VC runtime dll""" 48 version = _get_build_version() 49 if version is None: 50 # better be safe than sorry 51 return None 52 if version <= 6: 53 clibname = 'msvcrt' 54 else: 55 clibname = 'msvcr%d' % (version * 10) 56 57 # If python was built with in debug mode 58 import imp 59 if imp.get_suffixes()[0][0] == '_d.pyd': 60 clibname += 'd' 61 return clibname+'.dll' 62 63 def find_library(name): 64 if name in ('c', 'm'): 65 return find_msvcrt() 66 # See MSDN for the REAL search order. 67 for directory in os.environ['PATH'].split(os.pathsep): 68 fname = os.path.join(directory, name) 69 if os.path.isfile(fname): 70 return fname 71 if fname.lower().endswith(".dll"): 72 continue 73 fname = fname + ".dll" 74 if os.path.isfile(fname): 75 return fname 76 return None 77 78 if os.name == "ce": 79 # search path according to MSDN: 80 # - absolute path specified by filename 81 # - The .exe launch directory 82 # - the Windows directory 83 # - ROM dll files (where are they?) 84 # - OEM specified search path: HKLM\Loader\SystemPath 85 def find_library(name): 86 return name 87 88 if os.name == "posix" and sys.platform == "darwin": 89 from ctypes.macholib.dyld import dyld_find as _dyld_find 90 def find_library(name): 91 possible = ['lib%s.dylib' % name, 92 '%s.dylib' % name, 93 '%s.framework/%s' % (name, name)] 94 for name in possible: 95 try: 96 return _dyld_find(name) 97 except ValueError: 98 continue 99 return None 100 101 elif os.name == "posix": 102 # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump 103 import re, tempfile, errno 104 105 def _findLib_gcc(name): 106 expr = r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name) 107 fdout, ccout = tempfile.mkstemp() 108 os.close(fdout) 109 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;' \ 110 '$CC -Wl,-t -o ' + ccout + ' 2>&1 -l' + name 111 try: 112 f = os.popen(cmd) 113 try: 114 trace = f.read() 115 finally: 116 rv = f.close() 117 finally: 118 try: 119 os.unlink(ccout) 120 except OSError, e: 121 if e.errno != errno.ENOENT: 122 raise 123 if rv == 10: 124 raise OSError, 'gcc or cc command not found' 125 res = re.search(expr, trace) 126 if not res: 127 return None 128 return res.group(0) 129 130 131 if sys.platform == "sunos5": 132 # use /usr/ccs/bin/dump on solaris 133 def _get_soname(f): 134 if not f: 135 return None 136 cmd = "/usr/ccs/bin/dump -Lpv 2>/dev/null " + f 137 f = os.popen(cmd) 138 try: 139 data = f.read() 140 finally: 141 f.close() 142 res = re.search(r'\[.*\]\sSONAME\s+([^\s]+)', data) 143 if not res: 144 return None 145 return res.group(1) 146 else: 147 def _get_soname(f): 148 # assuming GNU binutils / ELF 149 if not f: 150 return None 151 cmd = 'if ! type objdump >/dev/null 2>&1; then exit 10; fi;' \ 152 "objdump -p -j .dynamic 2>/dev/null " + f 153 f = os.popen(cmd) 154 dump = f.read() 155 rv = f.close() 156 if rv == 10: 157 raise OSError, 'objdump command not found' 158 f = os.popen(cmd) 159 try: 160 data = f.read() 161 finally: 162 f.close() 163 res = re.search(r'\sSONAME\s+([^\s]+)', data) 164 if not res: 165 return None 166 return res.group(1) 167 168 if (sys.platform.startswith("freebsd") 169 or sys.platform.startswith("openbsd") 170 or sys.platform.startswith("dragonfly")): 171 172 def _num_version(libname): 173 # "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ] 174 parts = libname.split(".") 175 nums = [] 176 try: 177 while parts: 178 nums.insert(0, int(parts.pop())) 179 except ValueError: 180 pass 181 return nums or [ sys.maxint ] 182 183 def find_library(name): 184 ename = re.escape(name) 185 expr = r':-l%s\.\S+ => \S*/(lib%s\.\S+)' % (ename, ename) 186 f = os.popen('/sbin/ldconfig -r 2>/dev/null') 187 try: 188 data = f.read() 189 finally: 190 f.close() 191 res = re.findall(expr, data) 192 if not res: 193 return _get_soname(_findLib_gcc(name)) 194 res.sort(cmp= lambda x,y: cmp(_num_version(x), _num_version(y))) 195 return res[-1] 196 197 elif sys.platform == "sunos5": 198 199 def _findLib_crle(name, is64): 200 if not os.path.exists('/usr/bin/crle'): 201 return None 202 203 if is64: 204 cmd = 'env LC_ALL=C /usr/bin/crle -64 2>/dev/null' 205 else: 206 cmd = 'env LC_ALL=C /usr/bin/crle 2>/dev/null' 207 208 for line in os.popen(cmd).readlines(): 209 line = line.strip() 210 if line.startswith('Default Library Path (ELF):'): 211 paths = line.split()[4] 212 213 if not paths: 214 return None 215 216 for dir in paths.split(":"): 217 libfile = os.path.join(dir, "lib%s.so" % name) 218 if os.path.exists(libfile): 219 return libfile 220 221 return None 222 223 def find_library(name, is64 = False): 224 return _get_soname(_findLib_crle(name, is64) or _findLib_gcc(name)) 225 226 else: 227 228 def _findSoname_ldconfig(name): 229 import struct 230 if struct.calcsize('l') == 4: 231 machine = os.uname()[4] + '-32' 232 else: 233 machine = os.uname()[4] + '-64' 234 mach_map = { 235 'x86_64-64': 'libc6,x86-64', 236 'ppc64-64': 'libc6,64bit', 237 'sparc64-64': 'libc6,64bit', 238 's390x-64': 'libc6,64bit', 239 'ia64-64': 'libc6,IA-64', 240 } 241 abi_type = mach_map.get(machine, 'libc6') 242 243 # XXX assuming GLIBC's ldconfig (with option -p) 244 expr = r'\s+(lib%s\.[^\s]+)\s+\(%s' % (re.escape(name), abi_type) 245 f = os.popen('/sbin/ldconfig -p 2>/dev/null') 246 try: 247 data = f.read() 248 finally: 249 f.close() 250 res = re.search(expr, data) 251 if not res: 252 return None 253 return res.group(1) 254 255 def find_library(name): 256 return _findSoname_ldconfig(name) or _get_soname(_findLib_gcc(name)) 257 258 ################################################################ 259 # test code 260 261 def test(): 262 from ctypes import cdll 263 if os.name == "nt": 264 print cdll.msvcrt 265 print cdll.load("msvcrt") 266 print find_library("msvcrt") 267 268 if os.name == "posix": 269 # find and load_version 270 print find_library("m") 271 print find_library("c") 272 print find_library("bz2") 273 274 # getattr 275 ## print cdll.m 276 ## print cdll.bz2 277 278 # load 279 if sys.platform == "darwin": 280 print cdll.LoadLibrary("libm.dylib") 281 print cdll.LoadLibrary("libcrypto.dylib") 282 print cdll.LoadLibrary("libSystem.dylib") 283 print cdll.LoadLibrary("System.framework/System") 284 else: 285 print cdll.LoadLibrary("libm.so") 286 print cdll.LoadLibrary("libcrypt.so") 287 print find_library("crypt") 288 289 if __name__ == "__main__": 290 test() 291