在Python中释放打开的ctypes库 [英] Free the opened ctypes library in Python

查看:847
本文介绍了在Python中释放打开的ctypes库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道,如果我打开自己的c代码编译的dll库,如下所示:

I was wondering that, if I opened my own dll library compiled from custom c code, like this:

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?

Do I need to close the my_lib object after use, like a file object? Will doing this make the code cleaner, more efficient, and more "pythonic"?

谢谢!

推荐答案

一般来说,您不必免费使用共享库。考虑到CPython不提供从内存中卸载常规扩展模块的方法。例如,导入sqlite3将在进程的整个生命周期中加载_sqlite3扩展名和sqlite3共享库。卸载扩展与CPython使用指针作为对象ID的方式不兼容。访问取消分配(可能重复使用)的地址将是未定义的行为。

Generally you shouldn't have to free a shared library. Consider that CPython doesn't provide a means to unload a regular extension module from memory. For example, importing sqlite3 will load the _sqlite3 extension and sqlite3 shared library for the life of the process. Unloading extensions is incompatible with the way CPython uses pointers as object IDs. Accessing a deallocated (and possibly reused) address would be undefined behavior.

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

If you need to unload or reload a shared library, and are confident that it's safe, the _ctypes extension module has POSIX dlclose and Windows FreeLibrary, which call the system functions of the same name. Both take the library handle as the single argument. This is the _handle attribute of a CDLL instance. If unloading the library fails, OSError is raised.

dlclose FreeLibrary 通过递减句柄参考计数。当计数递减为0时,库将被卸载。计数最初为1,每次POSIX dlopen 或Windows LoadLibrary 被调用已加载的库。

Both dlclose and FreeLibrary work by decrementing the handle's reference count. The library is unloaded when the count is decremented to 0. The count is initially 1 and gets incremented each time POSIX dlopen or Windows LoadLibrary is called for an already loaded library.

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

这篇关于在Python中释放打开的ctypes库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆