6

几天来我一直在强调试图在 Windows 上编译 libuvc 的修改版本,现在我终于完成了,我似乎无法在 Python 上加载它。我已经在 Linux 机器上使用相同版本的 Python 编译并成功导入的这个库根本不喜欢 w10。

系统

  • 赢得 10 64 位
  • 蟒蛇3.8 64位
  • libusb 1.022
  • 使用 MinGW64 编译的 libuvc.dll

问题

当尝试

import ctypes
import ctypes.util
name = ctypes.util.find_library('libuvc')
lib = ctypes.cdll.LoadLibrary(name)

我收到以下错误:

Could not find module 'C:\Program Files (x86)\libuvc\lib\libuvc.dll'.
Try using the full path with constructor syntax. 
Error: could not find libuvc!

问题是该文件存在,因为它是由 util.find_library 找到的,但是 python 认为它不在它所在的位置,或者输出可能只是默认值。我在这里想念什么?什么可能导致无法加载模块,但无法找到它?对不起,我没有比这更多的输出。

PS:我尝试以不同的方式重新格式化字符串,但消息没有改变。

4

4 回答 4

14

Python 3. 8开始,.dll搜索机制发生了变化。

根据[Python.Docs]: os.add_dll_directory(path)重点是我的):

将路径添加到 DLL 搜索路径。

此搜索路径用于解析导入扩展模块的依赖关系(模块本身通过 sys.path 解析),也可以通过ctypes解析。

所以,你可以这样做:

os.add_dll_directory("${path_to_working_dlls_directoy}")

您可以检查[SO]: PyWin32 and Python 3.8.0 (@CristiFati's answer) (虽然看起来很不同,但有相同的原因),以获取更多详细信息。

于 2019-12-14T09:03:34.257 回答
8

晚了一年,但我已经弄清楚发生了什么以及如何解决它。如果您查看ctypes.CDLL大约第 340 行的代码,您会发现文档实际上是不正确的。代码将构造函数定义为

def __init__(self, name, mode=DEFAULT_MODE, handle=None,
             use_errno=False, use_last_error=False, winmode=None):

然而,文档说winmode=0. 如果您查看第 358 行,您会发现它非常重要。当 时,第374 行(别名为第110 行)使用的winmode=None搜索模式设置为第363 行。此搜索模式似乎不会响应对或的更改。_ctypes.LoadLibrary_dlopennt._LOAD_LIBRARY_SEARCH_DEFAULT_DIRSos.environ['PATH']sys.pathos.add_dll_directory

但是,如果您通过使用winmode=0而不是绕过该设置None,则库似乎可以正常加载。零是完整路径的有效模式(就像 一样nt._LOAD_WITH_ALTERED_SEARCH_PATH)。此处提供了完整的模式列表:https ://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa ,在dwFlags参数下。

正如@CristiFati指出的那样,Python 3.8 中的行为发生了变化。发生这种情况是因为在此之前,该winmode参数不存在。而是mode直接使用,默认值为ctypes.DEFAULT_MODE,恰好对应于零并且适用于所有平台。

解决差异的 Python 错误报告:https ://bugs.python.org/issue42114

于 2020-10-21T21:39:23.607 回答
2

好的,所以我修复了它,在从同一位置加载 dll 之前,我需要将工作目录更改为执行脚本的位置。

os.chdir('path_to_working_dlls_directoy')

不完全确定为什么这会有所帮助。

于 2019-12-14T02:18:32.290 回答
-2

您可以指定库的路径

import snap7
import struct
from snap7.common import Snap7Library
from snap7.util import *

# If you are using a different location for the library
Snap7Library(lib_location='C:/snap7/snap7.dll')
load_library() #Testing library is correctly <WinDLL 'C:\snap7\snap7.dll', handle 7ff9d5d90000 at 0x1a5a0417640>

plc = snap7.client.Client()
plc.connect("10.112.115.10",0,1)

于 2020-09-16T03:42:38.607 回答