释放Python中打开的ctypes库

时间:2014-02-14 03:41:52

标签: python dll ctypes

我想知道,如果我打开自己的自定义c代码编译的dll库,就像这样:

import ctypes
my_lib = ctypes.cdll.LoadLibrary('./my_dll.dll')
my_func = my_lib.my_func
# Stuff I want to do with func()

我是否需要在使用后关闭my_lib对象,就像文件对象一样?这样做会使代码更清晰,更有效,更“pythonic”吗?

谢谢!

1 个答案:

答案 0 :(得分:8)

通常,您不必释放共享库。考虑到CPython没有提供从内存中卸载常规扩展模块的方法。例如,导入sqlite3将在进程的生命周期中加载_sqlite3扩展和sqlite3共享库。卸载扩展与CPython使用指针作为对象ID的方式不兼容。访问已解除分配(可能重用)的地址将是未定义的行为。

如果您需要卸载或重新加载共享库,并确信它是安全的,则_ctypes扩展模块具有POSIX dlclose和Windows FreeLibrary,它们调用相同名称的系统函数。两者都将库句柄作为单个参数。这是_handle实例的CDLL属性。如果卸载库失败,则会引发OSError

dlcloseFreeLibrary都可以通过递减句柄的引用计数来工作。当计数递减到0时,将卸载库。计数最初为1,并且每次为已加载的库调用POSIX dlopen或Windows LoadLibrary时,计数都会递增。

POSIX示例

  
#include <stdio.h>

void __attribute__((constructor)) initialize()
{
    printf("initialize\n");
}

void __attribute__((destructor)) finalize()
{
    printf("finalize\n");
}

POSIX Python

  
>>> import ctypes
>>> lib1 = ctypes.CDLL('./lib.so')
initialize
>>> lib2 = ctypes.CDLL('./lib.so')
>>> lib1._handle == lib2._handle
True

>>> import _ctypes
>>> _ctypes.dlclose(lib1._handle)
>>> _ctypes.dlclose(lib1._handle)
finalize

>>> lib1 = ctypes.CDLL('./lib.so')
initialize
>>> _ctypes.dlclose(lib1._handle)
finalize

Windows示例

  
#include <stdio.h>
#include <windows.h>

void initialize()
{
    printf("initialize\n");
}

void finalize()
{
    printf("finalize\n");
}

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._handle
True

>>> import _ctypes
>>> _ctypes.FreeLibrary(lib1._handle)
>>> _ctypes.FreeLibrary(lib1._handle)
finalize

>>> lib1 = ctypes.CDLL('./lib.dll')  
initialize
>>> _ctypes.FreeLibrary(lib1._handle)
finalize