常見的陷阱

無法載入檔案

第一個可能的錯誤是無法載入庫。在這種情況下,通常會引發 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