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

问题描述:

在我的应用程序中,我使用boost_python和python 3.5.2。所有的源代码构建在Ubuntu 14什么是libpython3.so与从python 3.5.2源码构建的libpython3.5m.so相比较?

当我在Ubuntu内置的Python 3.5.2从源代码与--with-shared选择,我得到了libpython3.so(7.6kB)和libpython3.5m.so(12MB)。我假设大的是真正的接口,小的接口可能是将呼叫转发到真正的接口。

由于boost_python可能会假定客户端链接到python(https://svn.boost.org/trac/boost/ticket/2615),所以我将libpython3.so链接到我的应用程序。但是当我运行它时,我得到了未解决的符号错误。

ldd -r myappldd -r libboost_python.so都列出了所有可能在nm -D libpython3.5m.so中找到的python符号未解决。

# 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

+0

据我所知'3.5m'是具有不同内存管理器的'3.5' - 你甚至应该有'python3.5m'程序。 Python文档中有一些信息,但我不记得在哪里。 – furas

+0

Ubuntu/Mint的非官方Python回购 - 你可以从'Ubuntu 14.04'获得'Python 3.5.2' - https://launchpad.net/~fkrull/+archive/ubuntu/deadsnakes – furas

+0

谢谢@furas。 https://docs.python.org/3/extending/embedding.html给出了一个链接flasg的例子:-lpython3.4m,我想我应该使用'python3.5m.so'而不是'python3.so'现在。 –

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

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

稳定的ABI PEP确定了稳定的Python C API的一个子集,如果开发人员承诺维护子集的二进制兼容性,将不会对未来的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呢?所以,如果使用-lpython3扩展链接链接到libpython3.6m.so等,将有机会获得系统上安装的Python版本的运行时间。

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

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

+1

谢谢詹姆斯。在我的情况下,我应该在构建'boost_python'和我的应用程序时定义'Py_LIMITED_API',以使它们仅依赖于稳定的ABI部分。我会试一试。 –

+0

这当然值得一试。但是,如果'boost_python'无法在有限的API模式下编译,它可能不值得追求。 –