如何在 Python 中使用 ctypes 卸载 DLL?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/359498/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I unload a DLL using ctypes in Python?
提问by Tom Hennen
I'm using ctypes to load a DLL in Python. This works great.
我正在使用 ctypes 在 Python 中加载 DLL。这很好用。
Now we'd like to be able to reload that DLL at runtime.
现在我们希望能够在运行时重新加载该 DLL。
The straightforward approach would seem to be: 1. Unload DLL 2. Load DLL
直接的方法似乎是: 1. 卸载 DLL 2. 加载 DLL
Unfortunately I'm not sure what the correct way to unload the DLL is.
不幸的是,我不确定卸载 DLL 的正确方法是什么。
_ctypes.FreeLibrary is available, but private.
_ctypes.FreeLibrary 可用,但是是私有的。
Is there some other way to unload the DLL?
有没有其他方法可以卸载 DLL?
采纳答案by Piotr Lesnicki
you should be able to do it by disposing the object
你应该能够通过处理对象来做到这一点
mydll = ctypes.CDLL('...')
del mydll
mydll = ctypes.CDLL('...')
EDIT:Hop's comment is right, this unbinds the name, but garbage collection doesn't happen that quickly, in fact I even doubt it even releases the loaded library.
编辑:Hop 的评论是对的,这解除了名称的绑定,但垃圾收集不会那么快发生,事实上我什至怀疑它甚至会释放加载的库。
Ctypes doesn't seem to provide a clean way to release resources, it does only provide a _handle
field to the dlopen handle...
Ctypes 似乎没有提供一种干净的方式来释放资源,它只为_handle
dlopen 句柄提供了一个字段......
So the only way I see, a really, really non-clean way, is to system dependently dlclose the handle, but it is very very unclean, as moreover ctypes keeps internally references to this handle. So unloading takes something of the form:
所以我看到的唯一方法,一种非常非常不干净的方法,是系统依赖地 dlclose 句柄,但它非常非常不干净,而且 ctypes 保持对这个句柄的内部引用。因此卸载采用以下形式:
mydll = ctypes.CDLL('./mylib.so')
handle = mydll._handle
del mydll
while isLoaded('./mylib.so'):
dlclose(handle)
It's so unclean that I only checked it works using:
它太不干净了,我只使用以下方法检查它是否有效:
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)
回答by pyHazard
It is helpful to be able to unload the DLL so that you can rebuild the DLL without having to restart the session if you are using iPython or similar work flow. Working in windows I have only attempted to work with the windows DLL related methods.
如果您使用 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)
I don't know much of the internals so I'm not really sure how clean this is. I think that deleting mydll releases the Python resources and the FreeLibrary call tells windows to free it. I had assumed that freeing with FreeLibary first would have produced problems so I saved a copy of the library handle and freed it in the order shown in the example.
我不太了解内部结构,所以我不确定这有多干净。我认为删除 mydll 会释放 Python 资源,而 FreeLibrary 调用会告诉 Windows 释放它。我认为首先使用 FreeLibary 释放会产生问题,所以我保存了库句柄的副本并按照示例中显示的顺序释放它。
I based this method on ctypes unload dllwhich loaded the handle explicitly up front. The loading convention however does not work as cleanly as the simple "ctypes.cdll.LoadLibrary('test.dll')" so I opted for the method shown.
我将此方法基于ctypes unload dll,它预先明确加载了句柄。然而,加载约定不像简单的“ctypes.cdll.LoadLibrary('test.dll')”那么干净,所以我选择了显示的方法。
回答by chris
If you need this functionality, you could write 2 dlls where dll_A loads/Unloads library from dll_B. Use dll_A as as python interface-loader and passthrough for functions in dll_B.
如果您需要此功能,您可以编写 2 个 dll,其中 dll_A 从 dll_B 加载/卸载库。使用 dll_A 作为 python 接口加载器和 dll_B 中函数的传递。