python - 与从 python 3.5.2 源构建的 libpython3.5m.so 相比,libpython3.so 是什么?

标签 python dynamic-linking boost-python

在我的应用程序中,我使用 boost_python 和 python 3.5.2。全部由 Ubuntu 14 中的源代码构建。

当我在 Ubuntu 中使用 --with-shared 选项从源代码构建 Python 3.5.2 时,我得到了 libpython3.so (7.6kB) 和 libpython3 .5m.so (12MB)。我假设大的是真实的,小的可能是将调用转发到真实接口(interface)的东西。

因为 boost_python 可能假设客户端链接到 python ( https://svn.boost.org/trac/boost/ticket/2615 ),所以我将 libpython3.so 链接到我的应用程序。但是当我运行它时,出现未解析的符号错误。

ldd -r myappldd -r libboost_python.so 都列出了所有未解析的 python 符号,这些符号可以在 nm -D libpython3.5m.so 中找到

# ldd -r lib/libboost_python3.so
    linux-vdso.so.1 => (0x00007ffe767fb000)
    libstdc+.so.6 => /usr/lib/x86_64-linux-gnu/libstdc+.so.6 (0x00007f130a7a3000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f130a58d000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f130a1c8000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1309ec2000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f130acf4000)
undefined symbol: PyExc_ImportError (lib/libboost_python3.so)
undefined symbol: PyProperty_Type (lib/libboost_python3.so)
undefined symbol: PyExc_StopIteration (lib/libboost_python3.so)
undefined symbol: PyBool_Type (lib/libboost_python3.so)
undefined symbol: PyExc_ValueError (lib/libboost_python3.so)
undefined symbol: PyList_Type (lib/libboost_python3.so)
undefined symbol: _Py_NotImplementedStruct (lib/libboost_python3.so)
undefined symbol: PyExc_TypeError (lib/libboost_python3.so)
undefined symbol: PyDict_Type (lib/libboost_python3.so)
...

libpython3.so 依赖于 libpython3.5m.so 但它本身没有这些符号。

基于此,我认为我应该将我的应用程序与 libpython3.5m.so 链接,而不是与 libpython3.so 链接。但奇怪的是,如果我使用 LD_PRELOAD 加载 libpython3.so,那么这些符号会在 ldd -r libboost_python3.so

中找到
# LD_LIBRARY_PATH=lib LD_PRELOAD=lib/libpython3.so ldd -r lib/libboost_python3.so
    linux-vdso.so.1 => (0x00007ffcb51f0000)
    lib/libpython3.so (0x00007f6f728e3000)
    libstdc+.so.6 => /usr/lib/x86_64-linux-gnu/libstdc+.so.6     (0x00007f6f725df000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f6f723c9000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6f72004000)
    libpython3.5m.so.1.0 => lib/libpython3.5m.so.1.0 (0x00007f6f71ae1000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0     (0x00007f6f718c3000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f6f715bd000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f6f72d32000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f6f713b9000)
    libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f6f711b6000)

为什么要有 libpython3.so 以及如何使用它?或者我应该只直接使用 libpython3.5m.so 吗?

最佳答案

libpython3.so 库支持 PEP 384 -- Defining a Stable ABI .

从历史上看,Python 不保证次要版本发布之间(例如 3.4 和 3.5 之间)在 C 级别的 ABI 稳定性。它们可能是源代码兼容的,但某些结构可能会改变大小,或者结构成员会改变类型等。但是,ABI 的某些部分已经成熟并且在较长时期内保持稳定。

稳定的 ABI PEP 确定了稳定的 Python C API 的一个子集,如果开发人员 promise 维护该子集的二进制兼容性,则不会对 future 的 Python 开发施加不当限制。如果一个程序或扩展将自己限制为仅使用这个子集,那么理论上它可以在不同的 Python 版本中使用而无需重新编译。

一旦您使用稳定的 ABI 编译了一些代码,仍然存在如何链接到运行时的问题。对于 Python 3.5.x,您需要使用 -lpython3.5m 进行链接。对于 Python 3.6.x,您需要 -lpython3.6m。这就是 libpython3.so 的用武之地。

libpython3.so 库只有一个用途:对于 Python 3.5,它链接到 libpython3.5m.so,而在 3.6 上,它链接到 libpython3。 6m.so 等。因此,如果扩展链接使用 -lpython3,它将有权访问系统上安装的 Python 版本的运行时。

现在回到您原来的问题:除非您完全确定您只使用稳定 ABI 中的功能(在您的情况下意味着找出 libboost_python 是否仅使用稳定 ABI),那么您可能想要链接到版本化的 libpython3.5m.so

如果有疑问,您最好链接到版本库:如果您升级到较新版本的 Python,调试动态链接错误比调试由于 ABI 更改导致的段错误要容易得多。

关于python - 与从 python 3.5.2 源构建的 libpython3.5m.so 相比,libpython3.so 是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39863827/

相关文章:

python - 是否可以通过 ssh 启动 IPython session 并稍后重新登录?

python - 如何显示行中具有不同值的列?

objective-c - 有没有办法通过名称获取类(class)?

python - 将 unique_ptr 与 boost python 结合使用 - boost::shared_ptr 有效,但 unique_ptr 无效

python - TKinter - 使用网格布局的框架中的小部件不是 'sticking'

python - 创建名称中包含连续整数的多个按钮

linux - 如何从进程中卸载所有依赖的共享库?

linux - 如何设置一个.so库搜索其他.so库的路径?

boost - 了解 bjam 的目标以及如何指定新目标?

c++ - 使用 Boost::Python 用参数包装纯虚拟方法