ctypes ( [Python 3]: ctypes - библиотека сторонних функций для Python ) загружает библиотеки (на Nix ), используя dlopen . Согласно [man7]: DLOPEN (3) :
Если тот же общий объект загружается снова с помощью dlopen () , возвращается тот же дескриптор объекта. Динамический компоновщик поддерживает счетчик ссылок для дескрипторов объектов, поэтому динамически загруженный общий объект не освобождается до тех пор, пока dlclose () не будет вызываться для него столько раз, сколько dlopen () успешно выполнено это.
Я подготовил небольшой пример.
dll.c
#if defined(_WIN32)
# define DLL_EXPORT __declspec(dllexport)
#else
# define DLL_EXPORT
#endif
static int val = -1;
DLL_EXPORT int get() {
return val;
}
DLL_EXPORT void set(int i) {
val = i;
}
code.py
#!/usr/bin/env python3
import sys
import os
import shutil
import ctypes
DLL0_NAME = "./dll0.so"
DLL1_NAME = "./dll1.so"
DIR0_NAME = "dir0"
def get_dll_funcs(dll):
get_func = dll.get
get_func.argtypes = None
get_func.restype = ctypes.c_int
set_func = dll.set
set_func.argtypes = [ctypes.c_int]
set_func.restype = None
return get_func, set_func
def main():
os.makedirs(DIR0_NAME, exist_ok=True)
shutil.copy(DLL0_NAME, DIR0_NAME)
shutil.copy(DLL0_NAME, DLL1_NAME)
dll_names = [DLL0_NAME, os.path.abspath(DLL0_NAME), os.path.join(DIR0_NAME, DLL0_NAME), DLL1_NAME]
dlls = [ctypes.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} on {:s}\n".format(sys.version, sys.platform))
main()
выход
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q054243176]> ls
code.py dll.c
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q054243176]> gcc -o dll0.so -shared dll.c
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q054243176]> ls
code.py dll0.so dll.c
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q054243176]> ./code.py
Python 3.5.2 (default, Nov 12 2018, 13:43:14)
[GCC 5.4.0 20160609] on linux
Item 0 (./dll0.so) was loaded at 02437A80
Item 1 (/home/cfati/Work/Dev/StackOverflow/q054243176/dll0.so) was loaded at 02437A80
Item 2 (dir0/./dll0.so) was loaded at 02438690
Item 3 (./dll1.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
Как видно из выходных данных (также обратите внимание на атрибут _handle ), при попытке загрузить один и тот же .dll (через его путь) более одного раза (такое же поведение на Win ):
- Если он расположен по тому же пути (даже если он указан по-другому), фактически не загружает его снова, он просто увеличивает его refcount
- Если его имя или местоположение отличается, он загружается снова
Короче говоря, чтобы ответить на ваш вопрос: просто скопируйте его под другим именем и загрузите его.