Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
867 views
in Technique[技术] by (71.8m points)

dll - Free the opened ctypes library in Python

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()

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"?

Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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.

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 Example

#include <stdio.h>

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

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

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 Example

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

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

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

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...