使用Python ctypes,我们可以通过两种具有相同效果的方式获取C共享库的实例(例如标准数学):
import ctypes
from ctypes.util import find_library
libm1 = ctypes.CDLL(find_library('m'))
libm2 = ctypes.cdll.LoadLibrary(find_library('m'))
引用libm1和libm2是不同的(libm1 is libm2
=> False
),但在所有其他方面看起来都是等效的。事实上,相当简单的实现使这两个调用等效:
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)
return dll
def __getitem__(self, name):
return getattr(self, name)
def LoadLibrary(self, name):
return self._dlltype(name)
cdll = LibraryLoader(CDLL)
从代码中我们可以看到,通过调用__getattr__
,我们可以利用缓存机制。实际上,以下代码也将为您提供对libm.so的引用:
libm3 = ctypes.cdll[find_library('m')]
根据文档,这将在后续调用中返回与libm相同的引用。但是,这几乎从未在代码示例中完成 - 我假设因为它感觉笨重/非惯用。但LoadLibrary
跳过缓存机制并始终返回库的新实例。
那么LibraryLoader
类的目的是什么,尤其是LoadLibrary
函数?