Python 如何创建加载器实例'cdll'的属性?
从 还可以使用以下方法之一加载共享库: 对象,它们是LibraryLoader类的实例,通过 调用LoadLibrary()方法,或通过以下方式检索库 加载程序实例的属性 我为第一种方法找到了一个例子 我在想第二条路怎么走?特别是,如何创建加载程序实例Python 如何创建加载器实例'cdll'的属性?,python,python-3.x,shared-libraries,ctypes,dynamic-loading,Python,Python 3.x,Shared Libraries,Ctypes,Dynamic Loading,从 还可以使用以下方法之一加载共享库: 对象,它们是LibraryLoader类的实例,通过 调用LoadLibrary()方法,或通过以下方式检索库 加载程序实例的属性 我为第一种方法找到了一个例子 我在想第二条路怎么走?特别是,如何创建加载程序实例cdll的属性?我的问题来自 LibraryLoader的全部意义在于,当您访问它时,它会为您创建库。而cdll.LoadLibrary(“foo”)不会创建cdll.foo 我的实验有什么问题吗?为什么cdll.libc永远不存在 >>
cdll
的属性?我的问题来自
LibraryLoader的全部意义在于,当您访问它时,它会为您创建库。而cdll.LoadLibrary(“foo”)
不会创建cdll.foo
我的实验有什么问题吗?为什么cdll.libc
永远不存在
>>> from ctypes import *
>>> cdll.libc
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/ctypes/__init__.py", line 418, in __getattr__
dll = self._dlltype(name)
File "/usr/lib/python3.6/ctypes/__init__.py", line 348, in __init__
self._handle = _dlopen(self._name, mode)
OSError: libc: cannot open shared object file: No such file or directory
>>> cdll.LoadLibrary("libc.so.6")
<CDLL 'libc.so.6', handle 7f6afe03a000 at 0x7f6afc1afac8>
>>> cdll.libc
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/ctypes/__init__.py", line 418, in __getattr__
dll = self._dlltype(name)
File "/usr/lib/python3.6/ctypes/__init__.py", line 348, in __init__
self._handle = _dlopen(self._name, mode)
OSError: libc: cannot open shared object file: No such file or directory
>>> libc=cdll.LoadLibrary("libc.so.6")
>>> cdll.libc
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/ctypes/__init__.py", line 418, in __getattr__
dll = self._dlltype(name)
File "/usr/lib/python3.6/ctypes/__init__.py", line 348, in __init__
self._handle = _dlopen(self._name, mode)
OSError: libc: cannot open shared object file: No such file or directory
>>> CDLL("libc.so.6")
<CDLL 'libc.so.6', handle 7f6afe03a000 at 0x7f6afc1af978>
>>> cdll.libc
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/ctypes/__init__.py", line 418, in __getattr__
dll = self._dlltype(name)
File "/usr/lib/python3.6/ctypes/__init__.py", line 348, in __init__
self._handle = _dlopen(self._name, mode)
OSError: libc: cannot open shared object file: No such file or directory
>>> libc=CDLL("libc.so.6")
>>> cdll.libc
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/ctypes/__init__.py", line 418, in __getattr__
dll = self._dlltype(name)
File "/usr/lib/python3.6/ctypes/__init__.py", line 348, in __init__
self._handle = _dlopen(self._name, mode)
OSError: libc: cannot open shared object file: No such file or directory
>>> cdll.__dict__
{'_dlltype': <class 'ctypes.CDLL'>}
>>从ctypes导入*
>>>cdll.libc
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/usr/lib/python3.6/ctypes/_init__.py”,第418行,在_getattr中__
dll=self.\u dlltype(名称)
文件“/usr/lib/python3.6/ctypes/_init__.py”,第348行,在_init中__
self.\u handle=\u dlopen(self.\u名称,模式)
OS错误:libc:无法打开共享对象文件:没有此类文件或目录
>>>cdll.LoadLibrary(“libc.so.6”)
>>>cdll.libc
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/usr/lib/python3.6/ctypes/_init__.py”,第418行,在_getattr中__
dll=self.\u dlltype(名称)
文件“/usr/lib/python3.6/ctypes/_init__.py”,第348行,在_init中__
self.\u handle=\u dlopen(self.\u名称,模式)
OS错误:libc:无法打开共享对象文件:没有此类文件或目录
>>>libc=cdll.LoadLibrary(“libc.so.6”)
>>>cdll.libc
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/usr/lib/python3.6/ctypes/_init__.py”,第418行,在_getattr中__
dll=self.\u dlltype(名称)
文件“/usr/lib/python3.6/ctypes/_init__.py”,第348行,在_init中__
self.\u handle=\u dlopen(self.\u名称,模式)
OS错误:libc:无法打开共享对象文件:没有此类文件或目录
>>>CDLL(“libc.so.6”)
>>>cdll.libc
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/usr/lib/python3.6/ctypes/_init__.py”,第418行,在_getattr中__
dll=self.\u dlltype(名称)
文件“/usr/lib/python3.6/ctypes/_init__.py”,第348行,在_init中__
self.\u handle=\u dlopen(self.\u名称,模式)
OS错误:libc:无法打开共享对象文件:没有此类文件或目录
>>>libc=CDLL(“libc.so.6”)
>>>cdll.libc
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/usr/lib/python3.6/ctypes/_init__.py”,第418行,在_getattr中__
dll=self.\u dlltype(名称)
文件“/usr/lib/python3.6/ctypes/_init__.py”,第348行,在_init中__
self.\u handle=\u dlopen(self.\u名称,模式)
OS错误:libc:无法打开共享对象文件:没有此类文件或目录
>>>cdll.\uuu dict__
{u dlltype':}
示例(发生了什么):
@EDIT0:
嗯,在Ux(至少Lnx)上,事情并不那么好:
因此,Win行为不能在Ux上复制(不幸的是,
(点)不能作为属性名的一部分,以克服这一问题)。或者,链接器可以配置为隐式搜索.so文件?但这只能部分解决问题,因为许多库看起来像libc.so.6(或者AFAIK,在OSX上.so和.dylib都可以)。所有cdll.libc
语句都提出了OSError
类似ctypes.windell.user321
的情况下,user321
没有添加到windell
属性列表中。对于cdll.LoadLibrary(“libc.so.6”)
或cdll(“libc.so.6”)
在这些情况下(即使加载成功),属性也不会添加到cdll
(我的示例也包括在内)。添加属性到cdll
缺少什么步骤?@Tim因为cdll.libc
不起作用,使cdll
具有libc
属性的唯一方法是手动为该属性分配某些内容。但你为什么要这么做cdll
是一个方便的包装器,可以更轻松地加载共享库。如果它不起作用(比如在linux上),就避免它。
>>> 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']
# ...
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)
# ...
[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
#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]