压缩目录中dll上的ctypes.cdll.LoadLibrary

问题描述 投票:0回答:1

我希望借助StackOverflow来部署此软件!

此软件使用ctypes.cdll.LoadLibrary加载dll。部署后(由py2exe纠缠),该dll被藏在包含目录结构的zip中。 dll在此结构中有几个层次。 (我不确定这是否是一个相关的细节。)LoadLibrary失败,因为它找不到dll,因为它的路径是...\site.zip\app\dll32\lfx.dll

我在SO或Google上找不到任何相关内容。我正在考虑对LoadLibrary调用进行try-except,并在except块中,检查给定的路径是否指向压缩位置,然后解压缩并重试。

是否有更优美的方式从zip加载dll?

python python-2.7 zip ctypes
1个回答
0
投票

列出[Python 3.Docs]: ctypes - A foreign function library for Python

为了加载。dllCTypes使用:

两者都需要FS]上存在的[[有效文件名](或NULL,但这与此处无关)。您提供的文件名不符合标准,因为FS在路径中存在时不会自动处理。zip(或其他)文件。因此。dll在加载之前需要先解压。有多种方法可以执行此操作,以下是使用Context Manager[Python 3.Docs]: Data model - With Statement Context Managers)或CM的方法。

code00.py

#!/usr/bin/env python import sys import ctypes as ct import zipfile as zf import os if sys.platform[:3].lower() == "win": from ctypes import wintypes as wt unload_lib = ct.WinDLL("kernel32.dll").FreeLibrary unload_lib.argtypes = [wt.HMODULE] unload_lib.restype = wt.BOOL else: unload_lib = ct.CDLL(None).dlclose unload_lib.argtypes = [ct.c_void_p] unload_lib.restype = ct.c_int class ZippedDll(): def __init__(self, zip_file_name, member_file_name, loader=ct.CDLL, extract_path=None, suppress_exceptions=False): self.zip_file_name = zip_file_name self.member_file_name = member_file_name self.loader = loader self.extract_path = extract_path self.suppress_exceptions = suppress_exceptions self.dll_path = None self.dll = None def __enter__(self): self.dll_path = os.path.join(self.extract_path, self.member_file_name) if self.extract_path else self.member_file_name if os.path.exists(self.dll_path): self.dll_path = None raise OSError("Target file already exists") with zf.ZipFile(self.zip_file_name) as zip_file: zip_file.extract(self.member_file_name, path=self.extract_path if self.extract_path else None) try: self.dll = self.loader(self.dll_path) except OSError: if not self.__exit__(*sys.exc_info()): raise return self.dll def __exit__(self, exc_type, exc_val, exc_tb): if self.dll: unload_lib(self.dll._handle) self.dll = None if self.dll_path and os.path.isfile(self.dll_path): os.unlink(self.dll_path) self.dll_path = None return self.suppress_exceptions def main(*argv): with ZippedDll("arch.zip", "dir00/dll00.dll", loader=ct.WinDLL) as dll: print(dll._name, dll.dll00Func00) if __name__ == "__main__": print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform)) main(*sys.argv[1:]) print("\nDone.")

Notes

    对于此示例,我使用具有以下结构的存档文件[[arch.zip
    • dir00 /
    • dll0.dll
    (来自另一个
  • SO问题)
CM解压缩
  • 。dll
  • 并加载它,最后(退出with时)清理所有内容(中间目录除外)
    可以添加更多错误处理我没有测试
  • Nix
  • 部分
  • 输出:
  • e:\Work\Dev\StackOverflow\q060348430>"e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32 dir00/dll00.dll <_FuncPtr object at 0x000002A045422E18> Done.

    © www.soinside.com 2019 - 2024. All rights reserved.