91 lines
3.1 KiB
Python
91 lines
3.1 KiB
Python
import ctypes
|
|
import ctypes.util
|
|
import os
|
|
import sys
|
|
import platform
|
|
|
|
_here = os.path.dirname(__file__)
|
|
|
|
class ExternalLibraryError(Exception):
|
|
pass
|
|
|
|
architecture = platform.architecture()[0]
|
|
|
|
_windows_styles = ["{}", "lib{}", "lib{}_dynamic", "{}_dynamic"]
|
|
|
|
_other_styles = ["{}", "lib{}"]
|
|
|
|
if architecture == "32bit":
|
|
for arch_style in ["32bit", "32" "86", "win32", "x86", "_x86", "_32", "_win32", "_32bit"]:
|
|
for style in ["{}", "lib{}"]:
|
|
_windows_styles.append(style.format("{}"+arch_style))
|
|
|
|
elif architecture == "64bit":
|
|
for arch_style in ["64bit", "64" "86_64", "amd64", "win_amd64", "x86_64", "_x86_64", "_64", "_amd64", "_64bit"]:
|
|
for style in ["{}", "lib{}"]:
|
|
_windows_styles.append(style.format("{}"+arch_style))
|
|
|
|
_loaded_libraries = {}
|
|
|
|
run_tests = lambda lib, tests: [f(lib) for f in tests]
|
|
|
|
class ExternalLibrary:
|
|
@staticmethod
|
|
def load(name, paths = None, tests = []):
|
|
if name in _loaded_libraries:
|
|
return _loaded_libraries[name]
|
|
if sys.platform == "win32":
|
|
lib = ExternalLibrary.load_windows(name, paths, tests)
|
|
_loaded_libraries[name] = lib
|
|
return lib
|
|
else:
|
|
lib = ExternalLibrary.load_other(name, paths, tests)
|
|
_loaded_libraries[name] = lib
|
|
return lib
|
|
|
|
@staticmethod
|
|
def load_other(name, paths = None, tests = []):
|
|
os.environ["PATH"] += ";" + ";".join((os.getcwd(), _here))
|
|
if paths: os.environ["PATH"] += ";" + ";".join(paths)
|
|
|
|
for style in _other_styles:
|
|
candidate = style.format(name)
|
|
library = ctypes.util.find_library(candidate)
|
|
if library:
|
|
try:
|
|
lib = ctypes.CDLL(library)
|
|
if tests and all(run_tests(lib, tests)):
|
|
return lib
|
|
except:
|
|
pass
|
|
|
|
@staticmethod
|
|
def load_windows(name, paths = None, tests = []):
|
|
os.environ["PATH"] += ";" + ";".join((os.getcwd(), _here))
|
|
if paths: os.environ["PATH"] += ";" + ";".join(paths)
|
|
|
|
not_supported = [] # libraries that were found, but are not supported
|
|
for style in _windows_styles:
|
|
candidate = style.format(name)
|
|
library = ctypes.util.find_library(candidate)
|
|
if library:
|
|
try:
|
|
lib = ctypes.CDLL(library)
|
|
if tests and all(run_tests(lib, tests)):
|
|
return lib
|
|
not_supported.append(library)
|
|
except WindowsError:
|
|
pass
|
|
except OSError:
|
|
not_supported.append(library)
|
|
|
|
|
|
if not_supported:
|
|
raise ExternalLibraryError("library '{}' couldn't be loaded, because the following candidates were not supported:".format(name)
|
|
+ ("\n{}" * len(not_supported)).format(*not_supported))
|
|
|
|
raise ExternalLibraryError("library '{}' couldn't be loaded".format(name))
|
|
|
|
|
|
|
|
|