链接 boost 时未定义的引用 python

Undefined references when linking boost python

我刚开始使用 Linux。但我相信我已经完成了正确的设置步骤: Python 3.8.5 的 wget,成功了。 wget for boost 1.74, bootstrap, ./b2

并且 boost 安装并设置了除 Python 之外的所有内容,它没有自动检测到。经过几个小时的挫折,我可以通过以下方式找到 python:

./bootstrap.sh --with-python=python3.8

运行 ./b2 --debug-configuration --with-python

表示已在此处找到:

notice: [python-cfg] Details of this Python configuration: notice:
[python-cfg]   interpreter command: "/usr/local/bin/python3.8" notice:
[python-cfg]   include path: "/usr/local/include/python3.8" notice:
[python-cfg]   library path: "/usr/local/lib/python3.8/config"
"/usr/local/lib"

因此,为此我正在使用 boost include 和 python include 上述 b2 调试输出中提到的文件夹成功编译我的程序。我与 -lpython3.8 -lboost_python38 -lboost_system

类似地链接

显然找到了所有 3 个,因为它不会抱怨缺少库。

Parser.o: In function `_Py_DECREF':
Parser.cpp:(.text+0x5b): undefined reference to `_Py_Dealloc'
Parser.o: In function `sections_to_html(std::__cxx11::list<DivSection, std::allocator<DivSection> > const&)':
Parser.cpp:(.text+0x1eb3): undefined reference to `PyUnicode_FromString'
Parser.cpp:(.text+0x1edf): undefined reference to `PyUnicode_FromString'
Parser.o: In function `PyInit_Parser':
Parser.cpp:(.text+0x245b): undefined reference to `boost::python::detail::init_module(PyModuleDef&, void (*)())'
Parser.o: In function `boost::python::type_info::name() const':
Parser.cpp:(.text._ZNK5boost6python9type_info4nameEv[_ZNK5boost6python9type_info4nameEv]+0x1f): undefined reference to `boost::python::detail::gcc_demangle(char const*)'
Parser.o: In function `boost::python::api::object::object()':
Parser.cpp:(.text._ZN5boost6python3api6objectC2Ev[_ZN5boost6python3api6objectC5Ev]+0x14): undefined reference to `_Py_NoneStruct'
Parser.o: In function `_object* boost::python::expect_non_null<_object>(_object*)':
Parser.cpp:(.text._ZN5boost6python15expect_non_nullI7_objectEEPT_S4_[_ZN5boost6python15expect_non_nullI7_objectEEPT_S4_]+0x14): undefined reference to `boost::python::throw_error_already_set()'
Parser.o: In function `boost::python::tuple boost::python::make_tuple<boost::python::handle<_object>, boost::python::handle<_object> >(boost::python::handle<_object> const&, boost::python::handle<_object> const&)':
Parser.cpp:(.text._ZN5boost6python10make_tupleINS0_6handleI7_objectEES4_EENS0_5tupleERKT_RKT0_[_ZN5boost6python10make_tupleINS0_6handleI7_objectEES4_EENS0_5tupleERKT_RKT0_]+0x2c): undefined reference to `PyTuple_New'
Parser.cpp:(.text._ZN5boost6python10make_tupleINS0_6handleI7_objectEES4_EENS0_5tupleERKT_RKT0_[_ZN5boost6python10make_tupleINS0_6handleI7_objectEES4_EENS0_5tupleERKT_RKT0_]+0x51): undefined reference to `boost::python::api::object::object(boost::python::handle<_object> const&)'
Parser.cpp:(.text._ZN5boost6python10make_tupleINS0_6handleI7_objectEES4_EENS0_5tupleERKT_RKT0_[_ZN5boost6python10make_tupleINS0_6handleI7_objectEES4_EENS0_5tupleERKT_RKT0_]+0xda): undefined reference to `boost::python::api::object::object(boost::python::handle<_object> const&)'
Parser.o: In function `void boost::python::def<boost::python::tuple (*)(char const*)>(char const*, boost::python::tuple (*)(char const*))':
Parser.cpp:(.text._ZN5boost6python3defIPFNS0_5tupleEPKcEEEvS4_T_[_ZN5boost6python3defIPFNS0_5tupleEPKcEEEvS4_T_]+0x50): undefined reference to `boost::python::detail::scope_setattr_doc(char const*, boost::python::api::object const&, char const*)'
Parser.o: In function `boost::python::api::object boost::python::detail::make_function_aux<boost::python::tuple (*)(char const*), boost::python::default_call_policies, boost::mpl::vector2<boost::python::tuple, char const*> >(boost::python::tuple (*)(char const*), boost::python::default_call_policies     const&, boost::mpl::vector2<boost::python::tuple, char const*> const&)':
Parser.cpp:(.text._ZN5boost6python6detail17make_function_auxIPFNS0_5tupleEPKcENS0_21default_call_policiesENS_3mpl7vector2IS3_S5_EEEENS0_3api6objectET_RKT0_RKT1_    [_ZN5boost6python6detail17make_function_auxIPFNS0_5tupleEPKcENS0_21default_call_policiesENS_3mpl7vector2IS3_S5_EEEENS0_3api6objectET_RKT0_RKT1_]+0x67): undefined reference to `boost::python::objects::function_object(boost::python::objects::py_function const&)'
Parser.o: In function `boost::python::objects::py_function_impl_base::py_function_impl_base()':
Parser.cpp:(.text._ZN5boost6python7objects21py_function_impl_baseC2Ev[_ZN5boost6python7objects21py_function_impl_baseC5Ev]+0xb): undefined reference to `vtable for boost::python::objects::py_function_impl_base'
Parser.o:(.data.rel.ro._ZTVN5boost6python7objects23caller_py_function_implINS0_6detail6callerIPFNS0_5tupleEPKcENS0_21default_call_policiesENS_3mpl7vector2IS5_S7_EEEEEE    [_ZTVN5boost6python7objects23caller_py_function_implINS0_6detail6callerIPFNS0_5tupleEPKcENS0_21default_call_policiesENS_3mpl7vector2IS5_S7_EEEEEE]+0x30): undefined reference to `boost::python::objects::py_function_impl_base::max_arity() const'
Parser.o: In function `boost::python::objects::caller_py_function_impl<boost::python::detail::caller<boost::python::tuple (*)(char const*), boost::python::default_call_policies, boost::mpl::vector2<boost::python::tuple, char const*> > >::~caller_py_function_impl()':
Parser.cpp:(.text._ZN5boost6python7objects23caller_py_function_implINS0_6detail6callerIPFNS0_5tupleEPKcENS0_21default_call_policiesENS_3mpl7vector2IS5_S7_EEEEED2Ev    [_ZN5boost6python7objects23caller_py_function_implINS0_6detail6callerIPFNS0_5tupleEPKcENS0_21default_call_policiesENS_3mpl7vector2IS5_S7_EEEEED5Ev]+0x22): undefined reference to `boost::python::objects::py_function_impl_base::~py_function_impl_base()'
Parser.o:(.data.rel.ro._ZTIN5boost6python7objects23caller_py_function_implINS0_6detail6callerIPFNS0_5tupleEPKcENS0_21default_call_policiesENS_3mpl7vector2IS5_S7_EEEEEE    [_ZTIN5boost6python7objects23caller_py_function_implINS0_6detail6callerIPFNS0_5tupleEPKcENS0_21default_call_policiesENS_3mpl7vector2IS5_S7_EEEEEE]+0x10): undefined reference to `typeinfo for boost::python::objects::py_function_impl_base'
Parser.o: In function `boost::python::converter::pointer_arg_from_python<char const*>::pointer_arg_from_python(_object*)':
Parser.cpp:(.text._ZN5boost6python9converter23pointer_arg_from_pythonIPKcEC2EP7_object[_ZN5boost6python9converter23pointer_arg_from_pythonIPKcEC5EP7_object]+0x18): undefined reference to `_Py_NoneStruct'
Parser.cpp:(.text._ZN5boost6python9converter23pointer_arg_from_pythonIPKcEC2EP7_object[_ZN5boost6python9converter23pointer_arg_from_pythonIPKcEC5EP7_object]+0x34): undefined reference to `boost::python::converter::get_lvalue_from_python(_object*, boost::python::converter::registration const&)'
Parser.o: In function `boost::python::converter::pointer_arg_from_python<char const*>::operator()() const':
Parser.cpp:(.text._ZNK5boost6python9converter23pointer_arg_from_pythonIPKcEclEv[_ZNK5boost6python9converter23pointer_arg_from_pythonIPKcEclEv]+0x1e): undefined reference to `_Py_NoneStruct'
Parser.o: In function `boost::python::converter::expected_pytype_for_arg<boost::python::tuple>::get_pytype()':
Parser.cpp:(.text._ZN5boost6python9converter23expected_pytype_for_argINS0_5tupleEE10get_pytypeEv[_ZN5boost6python9converter23expected_pytype_for_argINS0_5tupleEE10get_pytypeEv]+0x1b): undefined reference to `boost::python::converter::registry::query(boost::python::type_info)'
Parser.cpp:(.text._ZN5boost6python9converter23expected_pytype_for_argINS0_5tupleEE10get_pytypeEv[_ZN5boost6python9converter23expected_pytype_for_argINS0_5tupleEE10get_pytypeEv]+0x32): undefined reference to `boost::python::converter::registration::expected_from_python_type() const'
Parser.o: In function `boost::python::converter::expected_pytype_for_arg<char const*>::get_pytype()':
Parser.cpp:(.text._ZN5boost6python9converter23expected_pytype_for_argIPKcE10get_pytypeEv[_ZN5boost6python9converter23expected_pytype_for_argIPKcE10get_pytypeEv]+0x1b): undefined reference to `boost::python::converter::registry::query(boost::python::type_info)'
Parser.cpp:(.text._ZN5boost6python9converter23expected_pytype_for_argIPKcE10get_pytypeEv[_ZN5boost6python9converter23expected_pytype_for_argIPKcE10get_pytypeEv]+0x32): undefined reference to `boost::python::converter::registration::expected_from_python_type() const'
Parser.o: In function `boost::python::converter::registration const& boost::python::converter::detail::registry_lookup2<char const volatile>(char const volatile& (*)())':
Parser.cpp:(.text._ZN5boost6python9converter6detail16registry_lookup2IVKcEERKNS1_12registrationEPFRT_vE[_ZN5boost6python9converter6detail16registry_lookup2IVKcEERKNS1_12registrationEPFRT_vE]+0x1f): undefined reference to `boost::python::converter::registry::lookup(boost::python::type_info)'
Parser.o: In function `boost::python::converter::pyobject_type<boost::python::tuple, &PyTuple_Type>::get_pytype()':
Parser.cpp:(.text._ZN5boost6python9converter13pyobject_typeINS0_5tupleEXadL_Z12PyTuple_TypeEEE10get_pytypeEv[_ZN5boost6python9converter13pyobject_typeINS0_5tupleEXadL_Z12PyTuple_TypeEEE10get_pytypeEv]+0x7): undefined reference to `PyTuple_Type'
collect2: error: ld returned 1 exit status
makefile:8: recipe for target 'Parser' failed
make: *** [Parser] Error 1

我看到一堆 boost 命名空间的东西出现了。

所以这让我相信,要么我编译的内容和链接的内容之间的名称混淆发生了变化,要么定义的差异导致了命名空间或其他差异。

但我不确定如何找出原因,假设我之前的假设是正确的。

编辑:我缩短了转储并说 'most' 似乎来自 boost,但 JaMiT 打电话给我。所以这是完整的转储。

编辑 2:我检查了我的 python 配置,结果是:

user@vm:/usr/local/lib/python3.8/config-3.8-x86_64-linux-gnu$ python python-config.py --cflags

-I/usr/local/include/python3.8 -I/usr/local/include/python3.8 -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall

user@vm:/usr/local/lib/python3.8/config-3.8-x86_64-linux-gnu$ python python-config.py --ldflags

-L/usr/local/lib/python3.8/config-3.8-x86_64-linux-gnu -lcrypt -lpthread -ldl -lutil -lm -lm

编辑 3:

我在 /usr/local/lib/python3.8/config-3.8-x86_64-linux-gnu 的 libpython3.8.a 上使用了 nm,发现 PyUnicode_FromString 和其他一些确实正确显示为类型 'T' function-with-param.

所以他们在那里。

感谢 'sehe' 提到库排序的评论,我做了一些 Google 搜索并找到了问题 - 我在 makefile 中的 linking 步骤是:

$(CC) $(COMMONFLAGS) $(LDFLAGS) $(LIBS) -o 解析器 Parser.o grammar.o words.o

我使用的附加库应该放在最后,例如:

$(CC) $(COMMONFLAGS) $(LDFLAGS) -o 解析器 Parser.o grammar.o words.o $(LIBS)

但是在 linker 调用中修复了上述参数顺序之后,我从 Python 中突然出现了额外的未定义引用,这在之前没有被报告过。

事实证明这不是问题,因为构建可执行文件只是第一步 - 确保代码编译并且我可以 link。

最后,为了获得构建模块的 makefile,我可以将其导入 Python,我需要使用 -fPIC 编译所有 cpp 文件,然后 link 使用 -shared -export-dynamic

不需要

Python 的库,所以我最终的库是 -lboost_python38 -lboost_system

将我的 LD_LIBRARY_PATH 设置为指向 boost /stage/lib 文件夹后,我能够导入我的 Parser.so 模块并且它工作正常。