小能豆

加载器实例`cdll`的属性是如何创建的?

py

我的实验是不是出了问题?为什么cdll.libc不存在?

>>> from ctypes import *
>>> cdll.libc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/ctypes/__init__.py", line 418, in __getattr__
    dll = self._dlltype(name)
  File "/usr/lib/python3.6/ctypes/__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: libc: cannot open shared object file: No such file or directory
>>> cdll.LoadLibrary("libc.so.6")
<CDLL 'libc.so.6', handle 7f6afe03a000 at 0x7f6afc1afac8>
>>> cdll.libc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/ctypes/__init__.py", line 418, in __getattr__
    dll = self._dlltype(name)
  File "/usr/lib/python3.6/ctypes/__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: libc: cannot open shared object file: No such file or directory
>>> libc=cdll.LoadLibrary("libc.so.6")
>>> cdll.libc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/ctypes/__init__.py", line 418, in __getattr__
    dll = self._dlltype(name)
  File "/usr/lib/python3.6/ctypes/__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: libc: cannot open shared object file: No such file or directory
>>> CDLL("libc.so.6")
<CDLL 'libc.so.6', handle 7f6afe03a000 at 0x7f6afc1af978>
>>> cdll.libc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/ctypes/__init__.py", line 418, in __getattr__
    dll = self._dlltype(name)
  File "/usr/lib/python3.6/ctypes/__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: libc: cannot open shared object file: No such file or directory

>>> libc=CDLL("libc.so.6")
>>> cdll.libc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/ctypes/__init__.py", line 418, in __getattr__
    dll = self._dlltype(name)
  File "/usr/lib/python3.6/ctypes/__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: libc: cannot open shared object file: No such file or directory
>>> cdll.__dict__
{'_dlltype': <class 'ctypes.CDLL'>}

阅读 13

收藏
2025-01-11

共1个答案

小能豆

从你的实验来看,ctypes.cdll.libc 不起作用,可能是因为默认情况下,ctypes 无法直接找到 libc 的共享库路径。

ctypes 中,cdll 是一个全局的 LibraryLoader 对象,它通过库的基本名称(例如 "libc")来查找共享库。但你的系统可能没有提供直接通过名称 libc 解析路径的方法,或者需要提供具体版本(如 libc.so.6)。

问题原因

  1. 系统差异:不同的 Linux 发行版对共享库的路径解析方式有所不同。在某些系统上,libc 的默认名称可能需要明确版本号,例如 libc.so.6
  2. 环境变量缺失:如果 LD_LIBRARY_PATH 没有正确设置,或者系统的动态链接器配置没有包含 libcctypes 可能找不到 libc
  3. ctypes 限制cdll 依赖的 LibraryLoader 并不会缓存你手动加载的库(例如 cdll.LoadLibrary("libc.so.6")),所以即使你成功加载了 libc.so.6cdll.libc 仍然会尝试重新查找并失败。

解决方法

方法 1:显式加载库

你可以直接加载库文件,而不是依赖 cdll.libc

from ctypes import CDLL

libc = CDLL("libc.so.6")  # 加载 libc 的具体版本

然后你可以直接使用 libc 对象调用函数。


方法 2:创建别名

如果你希望像 cdll.libc 那样通过全局访问,可以手动在 cdll 中注册:

from ctypes import CDLL, cdll

libc = CDLL("libc.so.6")  # 显式加载
cdll.libc = libc  # 手动注册

之后你可以通过 cdll.libc 访问。


方法 3:检查库路径

如果 cdll.libc 无法找到库,可以检查系统中共享库的路径:

ldconfig -p | grep libc

这将显示系统中已注册的共享库路径。如果路径中没有 libc.so.6,你可以手动将路径添加到 LD_LIBRARY_PATH

export LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:$LD_LIBRARY_PATH

然后重新运行脚本。


方法 4:符号链接

如果你的系统中只有 libc.so.6,但没有 libc,可以创建一个符号链接:

sudo ln -s /lib/x86_64-linux-gnu/libc.so.6 /lib/libc.so

这将允许 cdll.libc 使用默认名称 libc 加载库。


总结

最简单可靠的方法是直接使用 CDLL("libc.so.6") 显式加载库。如果你经常需要使用 cdll.libc,可以手动注册它(方法 2)。

2025-01-11