代码之家  ›  专栏  ›  技术社区  ›  Mad Physicist

ctypes.CDLL属性访问的行为

  •  0
  • Mad Physicist  · 技术社区  · 4 年前

    我正在从Windows上的DLL访问一个函数,尽管我怀疑Linux上也有类似的接口。我通常看到的方法是存储function对象,然后将其 argtypes 和/或 restype ,并使用它:

    import ctypes
    func = ctypes.windll.kernel32.FreeLibrary
    func.argtypes = [ctypes.wintypes.HMODULE]
    func.restype = ctypes.wintypes.BOOL
    
    # Call func(...)
    

    现在我可以使用这个函数从其他源卸载DLL。

    argtypes参数 重新键入 直接在 kernel32

    dll = ctypes.windll.kernel32
    dll.FreeLibrary.argtypes = [ctypes.wintypes.HMODULE]
    dll.FreeLibrary.restype = ctypes.wintypes.BOOL
    
    # Call dll.FreeLibrary(...)
    

    我知道这些属性是在 ctypes.CDLL 作为呼叫 __getitem__ (重定向自 __getattr__ ). 但是,我这样设置的类型 / 是缓存的,还是每次都会生成一个新的函数引用,就像方法绑定一样?

    我没有找到任何明确的文档,但我没有看到任何教程使用后一种方法。到目前为止,我只能通过ctypes的一些代码进行跟踪。以下 出现

    >>> ctypes.windll.kernel32.argtypes = [ctypes.wintypes.HMODULE]
    >>> ctypes.windll.kernel32.argtypes
    [ctypes.c_void_p]  # Correct alias
    >>> ctypes.windll.kernel32.argtypes = [ctypes.c_int]
    >>> ctypes.windll.kernel32.argtypes
    [ctypes.c_long]    # Correct alias
    

    注意

    我知道Windows DLL引用是缓存的全局引用。这只是一个示例,展示了方法对象的情况,以便读者可以使用预定义的对象,而不会使MCVE过于复杂。

    0 回复  |  直到 4 年前
        1
  •  0
  •   Mad Physicist    4 年前

    __getattr__ (Python 3.9),保证行为:

       def __getattr__(self, name):
           if name.startswith('__') and name.endswith('__'):
               raise AttributeError(name)
           func = self.__getitem__(name)
           setattr(self, name, func)
           return func
    

    一次 setattr 调用时,引用被隐藏在 __dict__ ,以后的查找将绕过 __获取属性__ 完全是。

    https://github.com/python/cpython/blob/2.5/Lib/ctypes/__init__.py#L358 . 文档中似乎没有明确说明此功能。