无法在Python中导入dll模块

时间:2019-12-13 23:06:08

标签: python windows ctypes uvc

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

系统

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

问题

尝试

[1,2]

我收到以下错误:

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

问题在于该文件存在,因为它是由util.find_library找到的,但是python认为它不存在,或者输出只是默认的。我在这里想念什么?有什么可能无法不仅加载模块而是找到模块?抱歉,我没有比这更多的输出了。

P.S:我尝试用不同的方式重新格式化字符串,但是消息没有改变。

4 个答案:

答案 0 :(得分:2)

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

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

然而,文档说winmode=0。如果您查看line 358,就会发现它很重要。当winmode=None时,{{3}中line 374_ctypes.LoadLibrary使用的搜索模式(在line 110中别名为_dlopen)在{{3 }}。此搜索模式似乎不响应对line 363os.environ['PATH']sys.path的更改。

但是,如果通过使用nt._LOAD_LIBRARY_SEARCH_DEFAULT_DIRS而不是winmode=0绕过该设置,则库似乎可以正常加载。零是完整路径的有效模式(就像None)。模式的完整列表位于此处:nt._LOAD_WITH_ALTERED_SEARCH_PATH参数下的os.add_dll_directory

https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa所示,该行为在Python 3.8中已更改。发生这种情况是因为在此之前,dwFlags参数不存在。而是直接使用winmode,其默认值为mode,该默认值恰好对应于零,并且可以在所有平台上使用。

Python错误报告以解决差异:@CristiFati

答案 1 :(得分:1)

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

str(func_regex(xml))
# 'data.frame': 3 obs. of  13 variables:
#  $ Id      : Factor w/ 3 levels "4","5","6": 1 2 3
#  $ Attrib1 : Factor w/ 3 levels "1","2","3": 1 2 3
#  $ Attrib2 : Factor w/ 3 levels "7","8","9": 1 2 3
#  $ Attrib3 : Factor w/ 2 levels "2008-07-31T21:42:52.667",..: 1 2 2
#  $ Attrib4 : Factor w/ 3 levels "348","645","649": 2 3 1
#  $ Attrib5 : Factor w/ 3 levels "2732","45103",..: 2 3 1
#  $ Attrib8 : Factor w/ 2 levels "11652943","34873": 1 1 2
#  $ Attrib10: Factor w/ 1 level "2019-09-03T17:25:25.207": 1 1 1
#  $ Attrib11: Factor w/ 1 level "2019-10-21T14:03:54.607": 1 1 1
#  $ Attrib13: Factor w/ 1 level "a|b|c|d|e|f|g": 1 1 1
#  $ Attrib14: Factor w/ 2 levels "13","342": 1 2 2
#  $ Attrib15: Factor w/ 2 levels "3","43": 1 2 2
#  $ Attrib16: Factor w/ 2 levels "49","767": 1 2 2

str(func_xml2(xml))
# 'data.frame': 3 obs. of  18 variables:
#  $ Id      : Factor w/ 3 levels "4","5","6": 1 2 3
#  $ Attrib1 : Factor w/ 3 levels "1","2","3": 1 2 3
#  $ Attrib2 : Factor w/ 3 levels "7","8","9": 1 2 3
#  $ Attrib3 : Factor w/ 2 levels "2008-07-31T21:42:52.667",..: 1 2 2
#  $ Attrib4 : Factor w/ 3 levels "348","645","649": 2 3 1
#  $ Attrib5 : Factor w/ 3 levels "2732","45103",..: 2 3 1
#  $ Attrib6 : Factor w/ 2 levels "djhfbsdjhfbijhsdbfjkdbnfkjndaskjfnskjdlnfkjlsdnf",..: 2 2 1
#  $ Attrib7 : Factor w/ 2 levels "8","9": 1 1 2
#  $ Attrib8 : Factor w/ 2 levels "11652943","34873": 1 1 2
#  $ Attrib9 : Factor w/ 2 levels "FHDHsf","Rich B": 2 2 1
#  $ Attrib10: Factor w/ 1 level "2019-09-03T17:25:25.207": 1 1 1
#  $ Attrib11: Factor w/ 1 level "2019-10-21T14:03:54.607": 1 1 1
#  $ Attrib12: Factor w/ 3 levels "1","2","3": 1 2 3
#  $ Attrib13: Factor w/ 1 level "a|b|c|d|e|f|g": 1 1 1
#  $ Attrib14: Factor w/ 2 levels "13","342": 1 2 2
#  $ Attrib15: Factor w/ 2 levels "3","43": 1 2 2
#  $ Attrib16: Factor w/ 2 levels "49","767": 1 2 2
#  $ Attrib17: Factor w/ 2 levels "2012-10-31T16:42:47.213",..: 1 1 2

不确定为什么这样做有帮助。

答案 2 :(得分:1)

Python 3.8 开始, .dll 搜索机制已更改。

根据[Python 3.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)(原因相同),以了解更多详细信息。

答案 3 :(得分:-1)

您可以指定库的路径

Private Sub DisplayTimeRemaining()
    Label1.Text = CountdownTimer1.Remaining.ToString("hh\:mm\:ss")
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    If CountdownTimer1.Enabled Then
        CountdownTimer1.Stop()
        CountdownTimer1.Reset()
        Button1.Text = "Start"
    Else
        Button1.Text = "Stop"
        CountdownTimer1.Reset()
        CountdownTimer1.Period = TimeSpan.FromMinutes(NumericUpDown1.Value * 5)
        CountdownTimer1.Start()
    End If

    DisplayTimeRemaining()
End Sub

Private Sub CountdownTimer1_Tick(sender As Object, e As EventArgs) Handles CountdownTimer1.Tick
    DisplayTimeRemaining()
End Sub

Private Sub CountdownTimer1_Expired(sender As Object, e As EventArgs) Handles CountdownTimer1.Expired
    Label1.Text = "Finished"
    Button1.Text = "Start"
End Sub