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
|
#-----------------------------------------------------------------------------
# Copyright (c) 2005-2023, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
"""
Hooks to make ctypes.CDLL, .PyDLL, etc. look in sys._MEIPASS first.
"""
import sys
def install():
"""
Install the hooks.
This must be done from a function as opposed to at module-level, because when the module is imported/executed,
the import machinery is not completely set up yet.
"""
import os
try:
import ctypes
except ImportError:
# ctypes is not included in the frozen application
return
def _frozen_name(name):
# If the given (file)name does not exist, fall back to searching for its basename in sys._MEIPASS, where
# PyInstaller usually collects shared libraries.
if name and not os.path.isfile(name):
frozen_name = os.path.join(sys._MEIPASS, os.path.basename(name))
if os.path.isfile(frozen_name):
name = frozen_name
return name
class PyInstallerImportError(OSError):
def __init__(self, name):
self.msg = (
"Failed to load dynlib/dll %r. Most likely this dynlib/dll was not found when the application "
"was frozen." % name
)
self.args = (self.msg,)
class PyInstallerCDLL(ctypes.CDLL):
def __init__(self, name, *args, **kwargs):
name = _frozen_name(name)
try:
super().__init__(name, *args, **kwargs)
except Exception as base_error:
raise PyInstallerImportError(name) from base_error
ctypes.CDLL = PyInstallerCDLL
ctypes.cdll = ctypes.LibraryLoader(PyInstallerCDLL)
class PyInstallerPyDLL(ctypes.PyDLL):
def __init__(self, name, *args, **kwargs):
name = _frozen_name(name)
try:
super().__init__(name, *args, **kwargs)
except Exception as base_error:
raise PyInstallerImportError(name) from base_error
ctypes.PyDLL = PyInstallerPyDLL
ctypes.pydll = ctypes.LibraryLoader(PyInstallerPyDLL)
if sys.platform.startswith('win'):
class PyInstallerWinDLL(ctypes.WinDLL):
def __init__(self, name, *args, **kwargs):
name = _frozen_name(name)
try:
super().__init__(name, *args, **kwargs)
except Exception as base_error:
raise PyInstallerImportError(name) from base_error
ctypes.WinDLL = PyInstallerWinDLL
ctypes.windll = ctypes.LibraryLoader(PyInstallerWinDLL)
class PyInstallerOleDLL(ctypes.OleDLL):
def __init__(self, name, *args, **kwargs):
name = _frozen_name(name)
try:
super().__init__(name, *args, **kwargs)
except Exception as base_error:
raise PyInstallerImportError(name) from base_error
ctypes.OleDLL = PyInstallerOleDLL
ctypes.oledll = ctypes.LibraryLoader(PyInstallerOleDLL)
try:
import ctypes.util
except ImportError:
# ctypes.util is not included in the frozen application
return
# Same implementation as ctypes.util.find_library, except it prepends sys._MEIPASS to the search directories.
def pyinstaller_find_library(name):
if name in ('c', 'm'):
return ctypes.util.find_msvcrt()
# See MSDN for the REAL search order.
search_dirs = [sys._MEIPASS] + os.environ['PATH'].split(os.pathsep)
for directory in search_dirs:
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
ctypes.util.find_library = pyinstaller_find_library
# On macOS insert sys._MEIPASS in the first position of the list of paths that ctypes uses to search for libraries.
#
# Note: 'ctypes' module will NOT be bundled with every app because code in this module is not scanned for module
# dependencies. It is safe to wrap 'ctypes' module into 'try/except ImportError' block.
if sys.platform.startswith('darwin'):
try:
from ctypes.macholib import dyld
dyld.DEFAULT_LIBRARY_FALLBACK.insert(0, sys._MEIPASS)
except ImportError:
# Do nothing when module 'ctypes' is not available.
pass
|