与从 python 3.5.2 源构建的 libpython3.5m.so 相比,libpython3.so 是什么?
What is libpython3.so compared with libpython3.5m.so built from python 3.5.2 source?
在我的应用程序中,我使用 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 可能假设客户 link 反对 python (https://svn.boost.org/trac/boost/ticket/2615),我 linked 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
但它本身没有这些符号。
我认为基于此我应该 link 我的应用程序 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 的一个稳定子集,如果开发人员致力于维护二进制兼容性,则不会对未来的 Python 开发施加不当限制对于子集。如果一个程序或扩展将自己限制为仅使用这个子集,那么理论上它可以在不同的 Python 版本中使用而无需重新编译。
一旦您使用稳定的 ABI 编译了一些代码,仍然存在如何 link 到运行时的问题。对于 Python 3.5.x,您需要 link 使用 -lpython3.5m
。对于 Python 3.6.x,您需要 -lpython3.6m
。这就是 libpython3.so
的用武之地。
libpython3.so
库只有一个用途:对于 Python 3.5,它 link 到 libpython3.5m.so
,而在 3.6 上,它 link 到 libpython3.6m.so
,等等。因此,如果扩展 links 使用 -lpython3
,它将可以访问系统上安装的 Python 版本的运行时。
现在回到你原来的问题:除非你绝对确定你只使用稳定 ABI 中的功能(在你的情况下意味着找出 libboost_python
是否只使用稳定 ABI),然后你可能想要 link 到版本化的 libpython3.5m.so
.
如果有疑问,你最好 link 使用版本化库:调试动态 link 错误比调试由于 ABI 变化引起的段错误要容易得多,如果你升级的话Python.
的较新版本
在我的应用程序中,我使用 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 可能假设客户 link 反对 python (https://svn.boost.org/trac/boost/ticket/2615),我 linked 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
但它本身没有这些符号。
我认为基于此我应该 link 我的应用程序 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 的一个稳定子集,如果开发人员致力于维护二进制兼容性,则不会对未来的 Python 开发施加不当限制对于子集。如果一个程序或扩展将自己限制为仅使用这个子集,那么理论上它可以在不同的 Python 版本中使用而无需重新编译。
一旦您使用稳定的 ABI 编译了一些代码,仍然存在如何 link 到运行时的问题。对于 Python 3.5.x,您需要 link 使用 -lpython3.5m
。对于 Python 3.6.x,您需要 -lpython3.6m
。这就是 libpython3.so
的用武之地。
libpython3.so
库只有一个用途:对于 Python 3.5,它 link 到 libpython3.5m.so
,而在 3.6 上,它 link 到 libpython3.6m.so
,等等。因此,如果扩展 links 使用 -lpython3
,它将可以访问系统上安装的 Python 版本的运行时。
现在回到你原来的问题:除非你绝对确定你只使用稳定 ABI 中的功能(在你的情况下意味着找出 libboost_python
是否只使用稳定 ABI),然后你可能想要 link 到版本化的 libpython3.5m.so
.
如果有疑问,你最好 link 使用版本化库:调试动态 link 错误比调试由于 ABI 变化引起的段错误要容易得多,如果你升级的话Python.
的较新版本