2008-12-11 483 views
13

我使用ctypes在Python中加载DLL。这很好。如何在Python中使用ctypes卸载DLL?

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

的简单的方法似乎是:1。 卸载DLL 2.加载DLL

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

_ctypes.FreeLibrary可用,但私有。

有没有其他的方式来卸载DLL?

+0

你有没有找到更好的答案,我的丑陋的方式?如果不是,你应该问他们的邮件列表,如果它不存在错误报告它。 'del'应该调用函数来释放资源! – 2009-01-22 15:00:19

回答

13

你应该能够做到这一点通过设置对象

mydll = ctypes.CDLL('...') 
del mydll 
mydll = ctypes.CDLL('...') 

编辑:合的评论是正确的,这解除绑定的名称,但是垃圾收集不会发生很快,其实我连怀疑它甚至会释放加载的库。

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) 
+0

我不知道,但我怀疑这卸载了dll。我猜想它只会从当前命名空间中的名称中删除绑定(按照语言引用) – hop 2008-12-11 16:17:54

+0

当共享库不能被refcount递减时,POSIX`dlclose`返回非零值,Windows`FreeLibrary`返回零。在这种情况下,`_ctypes.dlclose`和`_ctypes.FreeLibrary`(注意下划线)引发`OSError`。 – eryksun 2014-02-14 11:35:59

3

这是非常有意义的,能够卸载DLL,这样就可以重建DLL而无需在使用iPython或类似工作流时重新启动会话。在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')”那样干净,所以我选择了所示的方法。