Пример ( что происходит ):
>>> import sys
>>> import ctypes
>>> print("Python {:s} on {:s}".format(sys.version, sys.platform))
Python 3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32
>>>
>>> [item for item in dir(ctypes.windll) if "__" not in item]
['LoadLibrary', '_dlltype', 'kernel32']
>>>
>>> user32_dll = ctypes.windll.LoadLibrary("user32")
>>> user32_dll
<WinDLL 'user32', handle 7ff882810000 at 0x2434399b4e0>
>>> [item for item in dir(ctypes.windll) if "__" not in item]
['LoadLibrary', '_dlltype', 'kernel32']
>>>
>>> user32_dll = ctypes.WinDLL("user32")
>>> user32_dll
<WinDLL 'user32', handle 7ff882810000 at 0x2434399b4a8>
>>> [item for item in dir(ctypes.windll) if "__" not in item]
['LoadLibrary', '_dlltype', 'kernel32']
>>>
>>> user32_dll = ctypes.windll.user32
>>> user32_dll
<WinDLL 'user32', handle 7ff882810000 at 0x24343984d68>
>>> [item for item in dir(ctypes.windll) if "__" not in item]
['LoadLibrary', '_dlltype', 'kernel32', 'user32']
>>>
>>> ctypes.windll.user32
<WinDLL 'user32', handle 7ff882810000 at 0x24343984d68>
>>>
>>> ctypes.windll.user321
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "c:\install\x64\python\python\3.5\Lib\ctypes\__init__.py", line 421, in __getattr__
dll = self._dlltype(name)
File "c:\install\x64\python\python\3.5\Lib\ctypes\__init__.py", line 351, in __init__
self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] The specified module could not be found
>>>
>>> dir(ctypes.windll)
['LoadLibrary', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_dlltype', 'kernel32', 'user32']
Как это происходит - все это в "$ {PYTHON_SRC_DIR} / Lib / ctypes / __ init __. Py "
( [GitHub]: python / cpython - (основной) cpython / Lib / ctypes / __ init __. Py ).Я вставляю код для cdll
, поскольку windll
(который я использовал в приведенном выше примере) является просто оболочкой над ним (и для него потребуется немного больше кода):
# ...
class CDLL(object):
# ...
class LibraryLoader(object):
def __init__(self, dlltype):
self._dlltype = dlltype
def __getattr__(self, name):
if name[0] == '_':
raise AttributeError(name)
dll = self._dlltype(name)
setattr(self, name, dll) # @TODO - cfati: This is the key for always returning the same instance.
return dll
# ...
cdll = LibraryLoader(CDLL)
# ...
@ EDIT0 :
Хм, в Ux (по крайней мере Lnx ) все не так хорошо:
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q050838633]> ls
libcapi.so
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q050838633]> LD_LIBRARY_PATH=$(pwd) python3 -c "import ctypes; ctypes.cdll.LoadLibrary('libcapi.so')"
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q050838633]> LD_LIBRARY_PATH=$(pwd) python3 -c "import ctypes; ctypes.cdll.LoadLibrary('libcapi')"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/usr/lib/python3.5/ctypes/__init__.py", line 425, in LoadLibrary
return self._dlltype(name)
File "/usr/lib/python3.5/ctypes/__init__.py", line 347, in __init__
self._handle = _dlopen(self._name, mode)
OSError: libcapi: cannot open shared object file: No such file or directory
Это потому, что очевидно (в отличие от [MSDN]: функция LoadLibrary ), [man7]: DLOPEN (3) недобавьте (по умолчанию) расширение библиотеки ( .so ) к имени файла (если оно его еще не содержит).
code.c :
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char *argv[]) {
if (argc == 1) {
printf("Dll name required\n");
return 1;
}
void *handle = dlopen(argv[1], RTLD_NOW);
if (handle == NULL) {
printf("Could not load [%s]\n", argv[1]);
return 2;
} else {
printf("Successfully loaded [%s]\n", argv[1]);
dlclose(handle);
return 0;
}
}
Вывод :
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q050838633]> gcc code.c -Wl,-ldl
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q050838633]> ./a.out "libcapi.so"
Could not load [libcapi.so]
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q050838633]> LD_LIBRARY_PATH=$(pwd) ./a.out "libcapi.so"
Successfully loaded [libcapi.so]
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q050838633]> LD_LIBRARY_PATH=$(pwd) ./a.out "libcapi"
Could not load [libcapi]
Таким образом, поведение Win не может быть реплицировано на Ux (к сожалению, .
( точка ) не может быть частью имени атрибута, чтобы преодолеть это).Или, может быть, компоновщик можно настроить для неявного поиска файлов .so ?Но это только частично решит проблему, так как многие библиотеки выглядят как libc.so.6 (или AFAIK , на OSX и .so и .dylib OK ).