Python 如何创建加载器实例'cdll'的属性?

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永远不存在 >>

还可以使用以下方法之一加载共享库: 对象,它们是LibraryLoader类的实例,通过 调用LoadLibrary()方法,或通过以下方式检索库 加载程序实例的属性

我为第一种方法找到了一个例子

我在想第二条路怎么走?特别是,如何创建加载程序实例
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]