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

与从python 3.5.2源代码构建的libpython3.5m.so相比,libpython3.so是什么?,python,dynamic-linking,boost-python,Python,Dynamic Linking,Boost Python,在我的应用程序中,我使用boost_python和python 3.5.2。所有这些都是从Ubuntu 14的源代码构建的 当我使用Ubuntu中的共享选项从源代码构建Python 3.5.2时,我得到了libpython3.so(7.6kB)和libpython3.5m.so(12MB)。我假设大的是真实的,小的可能是将调用转发到真实接口的东西 由于boost_-python可能假设客户端链接到python(),因此我将libpython3.so链接到我的应用程序。但是当我运行它时,我得到了未

在我的应用程序中,我使用boost_python和python 3.5.2。所有这些都是从Ubuntu 14的源代码构建的

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

由于boost_-python可能假设客户端链接到python(),因此我将
libpython3.so
链接到我的应用程序。但是当我运行它时,我得到了未解决的符号错误

ldd-r myapp
ldd-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

libpython3.so
库就是用来支持的

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

稳定的ABI PEP确定了一个稳定的Python C API子集,如果开发人员致力于维护该子集的二进制兼容性,它不会对未来的Python开发造成不适当的限制。如果一个程序或扩展只限于使用这个子集,那么理论上它可以在不同的Python版本中使用,而无需重新编译

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


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

现在回到您最初的问题:除非您完全确定您只使用稳定的ABI中的功能(在您的情况下,这意味着确定
libboost\u python
是否只使用稳定的ABI),否则您可能希望链接到版本化的
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)
...

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

据我所知,
3.5m
3.5
具有不同的内存管理器-您甚至应该有程序
python3.5m
。Python文档中有一些信息,但我不记得在哪里。Ubuntu/Mint的非官方Python repo-你可以获得
Ubuntu 14.04的
Python 3.5.2
-谢谢@furas。给出了链接flasg的一个例子:-lpython3.4m,我想我现在应该使用
python3.5m.so
而不是
python3.so
。-似乎
m
使用
pymalloc
而不是
malloc
谢谢詹姆斯。在我的例子中,我应该定义
Py_LIMITED_API
,同时构建
boost_python
和我的应用程序,让它们只依赖于稳定的ABI部分。我要试一试。它当然值得一试。但如果
boost_python
无法在有限的API模式下编译,那么它可能就不值得追求了。