FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
Source.Python/addons/source-python/Python3/ctypes/util.py at master · waldotf/Source.Python · GitHub
waldotf
Source.Python
Repository navigation
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
Source.Python
/
addons
/
source-python
/
Python3
/
ctypes
/
util.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
388 lines (342 loc) · 13.9 KB
Breadcrumbs
Source.Python
/
addons
/
source-python
/
Python3
/
ctypes
/
util.py
Copy path
File metadata and controls
388 lines (342 loc) · 13.9 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
import
os
import
shutil
import
subprocess
import
sys
# find_library(name) returns the pathname of a library, or None.
if
os
.
name
==
"nt"
:
def
_get_build_version
():
"""Return the version of MSVC that was used to build Python.
For Python 2.3 and up, the version number is included in
sys.version. For earlier versions, assume the compiler is MSVC 6.
"""
# This function was copied from Lib/distutils/msvccompiler.py
prefix
=
"MSC v."
i
=
sys
.
version
.
find
(
prefix
)
if
i
==
-
1
:
return
6
i
=
i
+
len
(
prefix
)
s
,
rest
=
sys
.
version
[
i
:].
split
(
" "
,
1
)
majorVersion
=
int
(
s
[:
-
2
])
-
6
if
majorVersion
>=
13
:
majorVersion
+=
1
minorVersion
=
int
(
s
[
2
:
3
])
/
10.0
# I don't think paths are affected by minor version in version 6
if
majorVersion
==
6
:
minorVersion
=
0
if
majorVersion
>=
6
:
return
majorVersion
+
minorVersion
# else we don't know what version of the compiler this is
return
None
def
find_msvcrt
():
"""Return the name of the VC runtime dll"""
version
=
_get_build_version
()
if
version
is
None
:
# better be safe than sorry
return
None
if
version
<=
6
:
clibname
=
'msvcrt'
elif
version
<=
13
:
clibname
=
'msvcr%d'
%
(
version
*
10
)
else
:
# CRT is no longer directly loadable. See issue23606 for the
# discussion about alternative approaches.
return
None
# If python was built with in debug mode
import
importlib
.
machinery
if
'_d.pyd'
in
importlib
.
machinery
.
EXTENSION_SUFFIXES
:
clibname
+=
'd'
return
clibname
+
'.dll'
def
find_library
(
name
):
if
name
in
(
'c'
,
'm'
):
return
find_msvcrt
()
# See MSDN for the REAL search order.
for
directory
in
os
.
environ
[
'PATH'
].
split
(
os
.
pathsep
):
fname
=
os
.
path
.
join
(
directory
,
name
)
if
os
.
path
.
isfile
(
fname
):
return
fname
if
fname
.
lower
().
endswith
(
".dll"
):
continue
fname
=
fname
+
".dll"
if
os
.
path
.
isfile
(
fname
):
return
fname
return
None
elif
os
.
name
==
"posix"
and
sys
.
platform
in
{
"darwin"
,
"ios"
,
"tvos"
,
"watchos"
}:
from
ctypes
.
macholib
.
dyld
import
dyld_find
as
_dyld_find
def
find_library
(
name
):
possible
=
[
'lib%s.dylib'
%
name
,
'%s.dylib'
%
name
,
'%s.framework/%s'
%
(
name
,
name
)]
for
name
in
possible
:
try
:
return
_dyld_find
(
name
)
except
ValueError
:
continue
return
None
elif
sys
.
platform
.
startswith
(
"aix"
):
# AIX has two styles of storing shared libraries
# GNU auto_tools refer to these as svr4 and aix
# svr4 (System V Release 4) is a regular file, often with .so as suffix
# AIX style uses an archive (suffix .a) with members (e.g., shr.o, libssl.so)
# see issue#26439 and _aix.py for more details
from
ctypes
.
_aix
import
find_library
elif
sys
.
platform
==
"android"
:
def
find_library
(
name
):
directory
=
"/system/lib"
if
"64"
in
os
.
uname
().
machine
:
directory
+=
"64"
fname
=
f"
{
directory
}
/lib
{
name
}
.so"
return
fname
if
os
.
path
.
isfile
(
fname
)
else
None
elif
os
.
name
==
"posix"
:
# Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
import
re
,
tempfile
def
_is_elf
(
filename
):
"Return True if the given file is an ELF file"
elf_header
=
b'
\x7f
ELF'
try
:
with
open
(
filename
,
'br'
)
as
thefile
:
return
thefile
.
read
(
4
)
==
elf_header
except
FileNotFoundError
:
return
False
def
_findLib_gcc
(
name
):
# Run GCC's linker with the -t (aka --trace) option and examine the
# library name it prints out. The GCC command will fail because we
# haven't supplied a proper program with main(), but that does not
# matter.
expr
=
os
.
fsencode
(
r'[^\(\)\s]*lib%s\.[^\(\)\s]*'
%
re
.
escape
(
name
))
c_compiler
=
shutil
.
which
(
'gcc'
)
if
not
c_compiler
:
c_compiler
=
shutil
.
which
(
'cc'
)
if
not
c_compiler
:
# No C compiler available, give up
return
None
temp
=
tempfile
.
NamedTemporaryFile
()
try
:
args
=
[
c_compiler
,
'-Wl,-t'
,
'-o'
,
temp
.
name
,
'-l'
+
name
]
env
=
dict
(
os
.
environ
)
env
[
'LC_ALL'
]
=
'C'
env
[
'LANG'
]
=
'C'
try
:
proc
=
subprocess
.
Popen
(
args
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
STDOUT
,
env
=
env
)
except
OSError
:
# E.g. bad executable
return
None
with
proc
:
trace
=
proc
.
stdout
.
read
()
finally
:
try
:
temp
.
close
()
except
FileNotFoundError
:
# Raised if the file was already removed, which is the normal
# behaviour of GCC if linking fails
pass
res
=
re
.
findall
(
expr
,
trace
)
if
not
res
:
return
None
for
file
in
res
:
# Check if the given file is an elf file: gcc can report
# some files that are linker scripts and not actual
# shared objects. See bpo-41976 for more details
if
not
_is_elf
(
file
):
continue
return
os
.
fsdecode
(
file
)
if
sys
.
platform
==
"sunos5"
:
# use /usr/ccs/bin/dump on solaris
def
_get_soname
(
f
):
if
not
f
:
return
None
try
:
proc
=
subprocess
.
Popen
((
"/usr/ccs/bin/dump"
,
"-Lpv"
,
f
),
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
DEVNULL
)
except
OSError
:
# E.g. command not found
return
None
with
proc
:
data
=
proc
.
stdout
.
read
()
res
=
re
.
search
(
br'\[.*\]\sSONAME\s+([^\s]+)'
,
data
)
if
not
res
:
return
None
return
os
.
fsdecode
(
res
.
group
(
1
))
else
:
def
_get_soname
(
f
):
# assuming GNU binutils / ELF
if
not
f
:
return
None
objdump
=
shutil
.
which
(
'objdump'
)
if
not
objdump
:
# objdump is not available, give up
return
None
try
:
proc
=
subprocess
.
Popen
((
objdump
,
'-p'
,
'-j'
,
'.dynamic'
,
f
),
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
DEVNULL
)
except
OSError
:
# E.g. bad executable
return
None
with
proc
:
dump
=
proc
.
stdout
.
read
()
res
=
re
.
search
(
br'\sSONAME\s+([^\s]+)'
,
dump
)
if
not
res
:
return
None
return
os
.
fsdecode
(
res
.
group
(
1
))
if
sys
.
platform
.
startswith
((
"freebsd"
,
"openbsd"
,
"dragonfly"
)):
def
_num_version
(
libname
):
# "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ]
parts
=
libname
.
split
(
b"."
)
nums
=
[]
try
:
while
parts
:
nums
.
insert
(
0
,
int
(
parts
.
pop
()))
except
ValueError
:
pass
return
nums
or
[
sys
.
maxsize
]
def
find_library
(
name
):
ename
=
re
.
escape
(
name
)
expr
=
r':-l%s\.\S+ => \S*/(lib%s\.\S+)'
%
(
ename
,
ename
)
expr
=
os
.
fsencode
(
expr
)
try
:
proc
=
subprocess
.
Popen
((
'/sbin/ldconfig'
,
'-r'
),
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
DEVNULL
)
except
OSError
:
# E.g. command not found
data
=
b''
else
:
with
proc
:
data
=
proc
.
stdout
.
read
()
res
=
re
.
findall
(
expr
,
data
)
if
not
res
:
return
_get_soname
(
_findLib_gcc
(
name
))
res
.
sort
(
key
=
_num_version
)
return
os
.
fsdecode
(
res
[
-
1
])
elif
sys
.
platform
==
"sunos5"
:
def
_findLib_crle
(
name
,
is64
):
if
not
os
.
path
.
exists
(
'/usr/bin/crle'
):
return
None
env
=
dict
(
os
.
environ
)
env
[
'LC_ALL'
]
=
'C'
if
is64
:
args
=
(
'/usr/bin/crle'
,
'-64'
)
else
:
args
=
(
'/usr/bin/crle'
,)
paths
=
None
try
:
proc
=
subprocess
.
Popen
(
args
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
DEVNULL
,
env
=
env
)
except
OSError
:
# E.g. bad executable
return
None
with
proc
:
for
line
in
proc
.
stdout
:
line
=
line
.
strip
()
if
line
.
startswith
(
b'Default Library Path (ELF):'
):
paths
=
os
.
fsdecode
(
line
).
split
()[
4
]
if
not
paths
:
return
None
for
dir
in
paths
.
split
(
":"
):
libfile
=
os
.
path
.
join
(
dir
,
"lib%s.so"
%
name
)
if
os
.
path
.
exists
(
libfile
):
return
libfile
return
None
def
find_library
(
name
,
is64
=
False
):
return
_get_soname
(
_findLib_crle
(
name
,
is64
)
or
_findLib_gcc
(
name
))
else
:
def
_findSoname_ldconfig
(
name
):
import
struct
if
struct
.
calcsize
(
'l'
)
==
4
:
machine
=
os
.
uname
().
machine
+
'-32'
else
:
machine
=
os
.
uname
().
machine
+
'-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'
,
}
abi_type
=
mach_map
.
get
(
machine
,
'libc6'
)
# XXX assuming GLIBC's ldconfig (with option -p)
regex
=
r'\s+(lib%s\.[^\s]+)\s+\(%s'
regex
=
os
.
fsencode
(
regex
%
(
re
.
escape
(
name
),
abi_type
))
try
:
with
subprocess
.
Popen
([
'/sbin/ldconfig'
,
'-p'
],
stdin
=
subprocess
.
DEVNULL
,
stderr
=
subprocess
.
DEVNULL
,
stdout
=
subprocess
.
PIPE
,
env
=
{
'LC_ALL'
:
'C'
,
'LANG'
:
'C'
})
as
p
:
res
=
re
.
search
(
regex
,
p
.
stdout
.
read
())
if
res
:
return
os
.
fsdecode
(
res
.
group
(
1
))
except
OSError
:
pass
def
_findLib_ld
(
name
):
# See issue #9998 for why this is needed
expr
=
r'[^\(\)\s]*lib%s\.[^\(\)\s]*'
%
re
.
escape
(
name
)
cmd
=
[
'ld'
,
'-t'
]
libpath
=
os
.
environ
.
get
(
'LD_LIBRARY_PATH'
)
if
libpath
:
for
d
in
libpath
.
split
(
':'
):
cmd
.
extend
([
'-L'
,
d
])
cmd
.
extend
([
'-o'
,
os
.
devnull
,
'-l%s'
%
name
])
result
=
None
try
:
p
=
subprocess
.
Popen
(
cmd
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
,
universal_newlines
=
True
)
out
,
_
=
p
.
communicate
()
res
=
re
.
findall
(
expr
,
os
.
fsdecode
(
out
))
for
file
in
res
:
# Check if the given file is an elf file: gcc can report
# some files that are linker scripts and not actual
# shared objects. See bpo-41976 for more details
if
not
_is_elf
(
file
):
continue
return
os
.
fsdecode
(
file
)
except
Exception
:
pass
# result will be None
return
result
def
find_library
(
name
):
# See issue #9998
return
_findSoname_ldconfig
(
name
)
or
\
_get_soname
(
_findLib_gcc
(
name
))
or
_get_soname
(
_findLib_ld
(
name
))
################################################################
# test code
def
test
():
from
ctypes
import
cdll
if
os
.
name
==
"nt"
:
print
(
cdll
.
msvcrt
)
print
(
cdll
.
load
(
"msvcrt"
))
print
(
find_library
(
"msvcrt"
))
if
os
.
name
==
"posix"
:
# find and load_version
print
(
find_library
(
"m"
))
print
(
find_library
(
"c"
))
print
(
find_library
(
"bz2"
))
# load
if
sys
.
platform
==
"darwin"
:
print
(
cdll
.
LoadLibrary
(
"libm.dylib"
))
print
(
cdll
.
LoadLibrary
(
"libcrypto.dylib"
))
print
(
cdll
.
LoadLibrary
(
"libSystem.dylib"
))
print
(
cdll
.
LoadLibrary
(
"System.framework/System"
))
# issue-26439 - fix broken test call for AIX
elif
sys
.
platform
.
startswith
(
"aix"
):
from
ctypes
import
CDLL
if
sys
.
maxsize
<
2
**
32
:
print
(
f"Using CDLL(name, os.RTLD_MEMBER):
{
CDLL
(
'libc.a(shr.o)'
,
os
.
RTLD_MEMBER
)
}
"
)
print
(
f"Using cdll.LoadLibrary():
{
cdll
.
LoadLibrary
(
'libc.a(shr.o)'
)
}
"
)
# librpm.so is only available as 32-bit shared library
print
(
find_library
(
"rpm"
))
print
(
cdll
.
LoadLibrary
(
"librpm.so"
))
else
:
print
(
f"Using CDLL(name, os.RTLD_MEMBER):
{
CDLL
(
'libc.a(shr_64.o)'
,
os
.
RTLD_MEMBER
)
}
"
)
print
(
f"Using cdll.LoadLibrary():
{
cdll
.
LoadLibrary
(
'libc.a(shr_64.o)'
)
}
"
)
print
(
f"crypt
\t
::
{
find_library
(
'crypt'
)
}
"
)
print
(
f"crypt
\t
::
{
cdll
.
LoadLibrary
(
find_library
(
'crypt'
))
}
"
)
print
(
f"crypto
\t
::
{
find_library
(
'crypto'
)
}
"
)
print
(
f"crypto
\t
::
{
cdll
.
LoadLibrary
(
find_library
(
'crypto'
))
}
"
)
else
:
print
(
cdll
.
LoadLibrary
(
"libm.so"
))
print
(
cdll
.
LoadLibrary
(
"libcrypt.so"
))
print
(
find_library
(
"crypt"
))
if
__name__
==
"__main__"
:
test
()
Back
|
FazBrowse Home
|
New Git URL