2008-12-11 481 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')」那樣乾淨,所以我選擇了所示的方法。