首页 > 解决方案 > ctypes.CDLL() 和 ctypes.cdll.LoadLibrary() 有什么区别?

问题描述

这两种方法似乎都有效(对我来说),但似乎该CDLL()方法返回一个具有_handle属性的对象,该属性可用于通过ctypes.windll.kernel32.FreeLibrary()(至少在 Windows 上)卸载库 - 我还不知道如何在 Linux 上做到这一点)。

这两种方法有什么区别 - 为什么我会选择另一种?

最终,我的目标是能够在 Linux 上的两个 Windows 上加载和卸载库(因为我有一个第 3 方库,有时似乎会进入损坏状态 - 我希望卸载/重新加载会重置它)。

标签: pythonctypes

解决方案


[Python.Docs]中很好地解释了一切: ctypes - Python 的外部函数库

ctypes。CDLL ( name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0 )
       此类的实例表示已加载的共享库。这些库中的函数使用标准 C 调用约定,并假定返回int

...

ctypes。库加载器dlltype

...

LoadLibrary ( name )
      将共享库加载到进程中并返回。此方法始终返回库的新实例。

这些预制库加载器可用:

类型。cdll
      创建CDLL实例。

所以,第二种形式只是一个方便的包装,它们之间绝对没有功能上的区别,如下所示:

>>> import ctypes as ct
>>>
>>>
>>> k32_1 = ct.CDLL("kernel32.dll")  # 1.
>>> k32_2 = ct.cdll.LoadLibrary("kernel32.dll")  # 2.1.
>>> k32_3 = ct.cdll.kernel32  # 2.2.
>>>
>>> k32_1, k32_2, k32_3
(<CDLL 'kernel32.dll', handle 7fff59100000 at 0x2335c444ee0>, <CDLL 'kernel32.dll', handle 7fff59100000 at 0x2335b44bc10>, <CDLL 'kernel32', handle 7fff59100000 at 0x2335c45a790>)
>>> type(k32_1), type(k32_2), type(k32_3)
(<class 'ctypes.CDLL'>, <class 'ctypes.CDLL'>, <class 'ctypes.CDLL'>)
>>>
>>> k32_1._handle == k32_2._handle == k32_3._handle
True

使用最适合你的东西。第二种形式(#2.2.
)更短(我想这是它的目的)。#1。#2.1。是相同的(#2.1.可能更具解释性(因为它具有LoadLibrary))并且它们允许您从自定义路径加载库,或者扩展名不同于默认路径。就个人而言,#1。是我喜欢的那个。

有关更多详细信息,您可以查看[GitHub]:python/cpython - (master) cpython/Lib/ctypes/__init__.py,尤其是实现时的LibraryLoader ,它(cdll实际上是,并且)很容易理解。

只是提醒一下(可能您已经知道要进入什么内容了):加载和卸载库有时会很棘手。


推荐阅读