如何在Python中使用ctypes卸载DLL?

时间:2008-12-11 14:21:07

标签: python dll ctypes

我正在使用ctypes在Python中加载DLL。这很有效。

现在我们希望能够在运行时重新加载该DLL。

直截了当的做法似乎是: 1.卸载DLL 2.加载DLL

不幸的是我不确定卸载DLL的正确方法是什么。

_ctypes.FreeLibrary可用,但是私有。

还有其他方法可以卸载DLL吗?

3 个答案:

答案 0 :(得分:15)

你应该能够通过处置对象

来做到这一点
mydll = ctypes.CDLL('...')
del mydll
mydll = ctypes.CDLL('...')

编辑: Hop的评论是正确的,这取消了绑定名称,但垃圾收集不会很快发生,事实上我甚至怀疑它甚至会释放加载的库。

Ctypes似乎没有提供一种释放资源的简洁方法,它只为dlopen句柄提供了一个_handle字段......

所以我看到的唯一方法,一个真正的,真正非干净的方式,是系统依赖dlclose句柄,但它是非常非常不洁,因为此外ctypes保持内部引用此句柄。所以卸载需要采取以下形式:

mydll = ctypes.CDLL('./mylib.so')
handle = mydll._handle
del mydll
while isLoaded('./mylib.so'):
    dlclose(handle)

这是如此不洁,以至于我只使用以下方式检查了它:

def isLoaded(lib):
   libp = os.path.abspath(lib)
   ret = os.system("lsof -p %d | grep %s > /dev/null" % (os.getpid(), libp))
   return (ret == 0)

def dlclose(handle)
   libdl = ctypes.CDLL("libdl.so")
   libdl.dlclose(handle)

答案 1 :(得分:4)

如果您正在使用iPython或类似的工作流程,则可以卸载DLL以便重建DLL而无需重新启动会话。在Windows中工作我只尝试使用与Windows DLL相关的方法。

REBUILD = True
if REBUILD:
  from subprocess import call
  call('g++ -c -DBUILDING_EXAMPLE_DLL test.cpp')
  call('g++ -shared -o test.dll test.o -Wl,--out-implib,test.a')

import ctypes
import numpy

# Simplest way to load the DLL
mydll = ctypes.cdll.LoadLibrary('test.dll')

# Call a function in the DLL
print mydll.test(10)

# Unload the DLL so that it can be rebuilt
libHandle = mydll._handle
del mydll
ctypes.windll.kernel32.FreeLibrary(libHandle)

我不太了解内部因素,所以我不确定这是多么干净。我认为删除mydll释放Python资源,FreeLibrary调用告诉windows释放它。我曾假设首先释放FreeLibary会产生问题所以我保存了一个库句柄的副本并按照示例中显示的顺序释放它。

我将此方法基于ctypes unload dll,它在前面明确加载了句柄。然而,加载约定并不像简单的" ctypes.cdll.LoadLibrary(' test.dll')"那样干净利落。所以我选择了显示的方法。

答案 2 :(得分:1)

如果您需要此功能,可以编写2个dll,其中dll_A从dll_B加载/卸载库。对于dll_B中的函数,使用dll_A作为python接口加载器和passthrough。

豫ICP备18024241号-1