[Python.Docs]: ctypes - A foreign function library for Python loads libraries (on Nix) using DlOpen. According to [Man7]: DLOPEN(3):
If the same shared object is loaded again with dlopen(), the same object handle is returned. The dynamic linker maintains reference counts for object handles, so a dynamically loaded shared object is not deallocated until dlclose() has been called on it as many times as dlopen() has succeeded on it.
I've prepared a small example.
Before going further, check [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer) for details on a bug frequently encountered (also in the question) when working with CTypes.
dll00.c:
#if defined(_WIN32)
# define DLL00_EXPORT_API __declspec(dllexport)
#else
# define DLL00_EXPORT_API
#endif
static int val = -1;
DLL00_EXPORT_API int get()
{
return val;
}
DLL00_EXPORT_API void set(int i)
{
val = i;
}
code00.py:
#!/usr/bin/env python
import ctypes as cts
import os
import shutil
import sys
def get_dll_funcs(dll):
get_func = dll.get
get_func.argtypes = ()
get_func.restype = cts.c_int
set_func = dll.set
set_func.argtypes = (cts.c_int,)
set_func.restype = None
return get_func, set_func
def main(*argv):
dll00 = "./dll00.so"
dll01 = "./dll01.so"
dir00 = "dir00"
os.makedirs(dir00, exist_ok=True)
shutil.copy(dll00, dir00)
shutil.copy(dll00, dll01)
dll_names = [dll00, os.path.abspath(dll00), os.path.join(dir00, dll00), dll01]
dlls = [cts.CDLL(item) for item in dll_names]
for idx, dll in enumerate(dlls):
print("Item {:d} ({:s}) was loaded at {:08X}".format(idx, dll_names[idx], dll._handle))
set_func = get_dll_funcs(dll)[1]
set_func(idx * 10)
for idx, dll in enumerate(dlls):
get_func = get_dll_funcs(dll)[0]
print("Item {:d} get() returned {: d}".format(idx, get_func()))
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.\n")
sys.exit(rc)
Output:
[cfati@cfati-5510-0:/mnt/e/Work/Dev/StackOverflow/q054243176]> ~/sopr.sh
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###
[064bit prompt]>ls
code00.py dll00.c
[064bit prompt]> gcc -fPIC -shared -o dll00.so dll00.c
[064bit prompt]> ls
code00.py dll00.c dll00.so
[064bit prompt]> python ./code.py
Python 3.5.2 (default, Nov 12 2018, 13:43:14) [GCC 5.4.0 20160609] 064bit on linux
Item 0 (./dll00.so) was loaded at 02437A80
Item 1 (/mnt/e/Work/Dev/StackOverflow/q054243176/dll00.so) was loaded at 02437A80
Item 2 (dir00/./dll00.so) was loaded at 02438690
Item 3 (./dll01.so) was loaded at 02438EF0
Item 0 get() returned 10
Item 1 get() returned 10
Item 2 get() returned 20
Item 3 get() returned 30
As seen from the output (also pay attention to the _handle attribute), trying to load the same .dll (via its path) more than once (same behavior on Win):
If located in the same path (even if it's differently specified), doesn't actually load it again, it just increases its RefCount
If either its name or location differs, it is loaded again
In short, to answer your question: simply copy it under a different name and load that.