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