Как я могу выгрузить DLL с помощью ctypes в Python?
Я использую ctypes для загрузки DLL в Python. Это отлично работает.
Теперь мы хотели бы перезагрузить эту DLL во время выполнения.
Прямым подходом будет:
1. Выгрузить DLL
2. Загрузите DLL
К сожалению, я не уверен, какой правильный способ выгрузить DLL.
_ctypes.FreeLibrary доступен, но закрыт.
Есть ли другой способ выгрузить DLL?
Ответы
Ответ 1
вы должны иметь возможность сделать это, удалив объект
mydll = ctypes.CDLL('...')
del mydll
mydll = ctypes.CDLL('...')
EDIT: Комментарий хопа прав, это откручивает имя, но сборка мусора происходит не так быстро, на самом деле я даже сомневаюсь, что он даже выпускает загруженную библиотеку.
Ctypes, похоже, не обеспечивает чистый способ освобождения ресурсов, он предоставляет только поле _handle
дескриптору dlopen...
Таким образом, единственный способ, который я вижу, действительно, действительно нечистый путь, - это зависящий от системы 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)
Ответ 2
Полезно иметь возможность выгружать 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 сообщает окнам, чтобы освободить его. Я предположил, что освобождение FreeLibary сначала создало бы проблемы, поэтому я сохранил копию обработчика библиотеки и освободил ее в порядке, показанном в примере.
Я основал этот метод на ctypes unload dll, который явно загрузил дескриптор. Соглашение о загрузке, однако, работает не так просто, как простая "ctypes.cdll.LoadLibrary(" test.dll "), поэтому я выбрал показанный метод.