
通常,您不必释放共享库。考虑到CPython没有提供从内存中卸载常规扩展模块的方法。例如,导入sqlite3将在整个过程中加载_sqlite3扩展名和sqlite3共享库。卸载扩展与CPython使用指针作为对象ID的方式不兼容。访问已释放地址(并可能重用)的地址将是未定义的行为。
如果您需要卸载或重新加载共享库,并且确信它是安全的,则_ctypes扩展模块具有POSIX
dlclose和Windows
FreeLibrary,它们可以调用相同名称的系统函数。两者都将库句柄作为单个参数。这是实例的
_handle属性
CDLL。如果卸载库失败,
OSError则会引发。
双方
dlclose并
FreeLibrary通过减小手柄的引用计数工作。当计数递减为0时,库将被卸载。计数最初为1,并且每次为已加载的库调用POSIX
dlopen或Windows时,计数都会增加
LoadLibrary。
POSIX示例
#include <stdio.h>void __attribute__((constructor)) initialize(){ printf("initializen");}void __attribute__((destructor)) finalize(){ printf("finalizen");}POSIX Python
>>> import ctypes>>> lib1 = ctypes.CDLL('./lib.so')initialize>>> lib2 = ctypes.CDLL('./lib.so')>>> lib1._handle == lib2._handleTrue>>> import _ctypes>>> _ctypes.dlclose(lib1._handle)>>> _ctypes.dlclose(lib1._handle)finalize>>> lib1 = ctypes.CDLL('./lib.so')initialize>>> _ctypes.dlclose(lib1._handle)finalizeWindows示例
#include <stdio.h>#include <windows.h>void initialize(){ printf("initializen");}void finalize(){ printf("finalizen");}BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved){ switch(fdwReason) { case DLL_PROCESS_ATTACH: initialize(); break; case DLL_PROCESS_DETACH: finalize(); } return TRUE;}Windows Python
>>> import ctypes>>> lib1 = ctypes.CDLL('./lib.dll')initialize>>> lib2 = ctypes.CDLL('./lib.dll')>>> lib1._handle == lib2._handleTrue>>> import _ctypes>>> _ctypes.FreeLibrary(lib1._handle)>>> _ctypes.FreeLibrary(lib1._handle)finalize>>> lib1 = ctypes.CDLL('./lib.dll') initialize>>> _ctypes.FreeLibrary(lib1._handle)finalize欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)