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