常见的陷阱

无法加载文件

第一个可能的错误是无法加载库。在这种情况下,通常会引发 OSError。

这是因为该文件不存在(或 OS 无法找到):

>>> cdll.LoadLibrary("foobar.so")
Traceback (most recent call last):
File "<stdin>", 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: foobar.so: cannot open shared object file: No such file or directory

正如你所看到的,错误很明显且非常具有指示性。

第二个原因是找到了文件,但格式不正确。

>>> cdll.LoadLibrary("libc.so")
Traceback (most recent call last):
File "<stdin>", 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: /usr/lib/i386-linux-gnu/libc.so: invalid ELF header

在这种情况下,文件是脚本文件而不是 .so 文件。尝试在 Linux 机器上打开 .dll 文件或在 32 位 python 解释器上打开 64 位文件时,也可能发生这种情况。正如你所看到的,在这种情况下,错误更加模糊,需要进行一些挖掘。

无法访问功能

假设我们成功加载了 .so 文件,那么我们需要访问我们的函数,就像我们在第一个例子中所做的那样。

当使用不存在的函数时,会引发 AttributeError

>>> libc.foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.5/ctypes/__init__.py", line 360, in __getattr__
    func = self.__getitem__(name)
File "/usr/lib/python3.5/ctypes/__init__.py", line 365, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /lib/i386-linux-gnu/libc.so.6: undefined symbol: foo