在我的应用程序中,我使用boost_python和python 3.5.2。全部都是从Ubuntu 14中的源码构建的。
当我在Ubuntu中使用--with-shared
选项从源代码构建Python 3.5.2时,我得到libpython3.so
(7.6kB)和libpython3.5m.so
(12MB)。我认为大的是真实的,小的可能是转发到真实接口的呼叫。
由于boost_python可能假定客户端链接到python(https://svn.boost.org/trac/boost/ticket/2615),我将libpython3.so
与我的应用程序链接。但是当我运行它时,我得到了未解决的符号错误。
ldd -r myapp
或ldd -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
?
答案 0 :(得分:3)
libpython3.so
库可以支持PEP 384 -- Defining a Stable ABI。
从历史上看,Python并未保证次要版本发行版之间的C级ABI稳定性(例如3.4到3.5之间)。它们可能是源兼容的,但某些结构可能会改变大小,或者结构成员会改变类型等。但是,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,它链接到libpython3.6m.so
,等等。所以如果扩展链接使用{{1它可以访问系统上安装的Python版本的运行时。
现在回到原来的问题:除非你绝对确定你只使用稳定ABI中的功能(在你的情况下意味着找出-lpython3
是否只使用稳定的ABI),那么你可能想要链接到版本化的libboost_python
。
如果有疑问,最好不要链接到版本化的库:如果你升级到更新版本的Python,调试动态链接错误比由于ABI更改而导致的段错误要容易得多。