Free the opened ctypes library in Python
ctypes, dll, python
Solution
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\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 Example
#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
Problem
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!