因为一些原因,楼主想在Apollo自动驾驶框架里使用Boost.python工具来用C++ 调用Python,从网上找了个例子想编译下试试。
C++代码如下(boost.python/EmbeddingPython - Python Wiki):
#include <boost/python.hpp>
using namespace boost::python;
int main( int argc, char ** argv ) {
try {
Py_Initialize();
object main_module((
handle<>(borrowed(PyImport_AddModule("__main__")))));
object main_namespace = main_module.attr("__dict__");
handle<> ignored(( PyRun_String( "print (\"Hello, World\")",
Py_file_input,
main_namespace.ptr(),
main_namespace.ptr() ) ));
} catch( error_already_set ) {
PyErr_Print();
}
}
BUILD文件如下:
cc_binary(
name = "hello",
srcs = [
"hello.cc",
],
deps = [
#"@local_config_python//:python_headers",
#"@local_config_python//:python_lib",
"@boost",
],
)
一开始没有引入local_config_python的两个依赖,导致出现
external/boost/boost/python/detail/wrap_python.hpp:50:11: fatal error: 'pyconfig.h' file not found
去掉注释后就好了。
然后使用bazel编译这个模块时出现了报错信息
(01:50:17) ERROR: /apollo/modules/zj_prediction/BUILD:52:10: Linking of rule '//modules/zj_prediction:hello' failed (Exit 1): crosstool_wrapper_driver_is_not_gcc failed: error executing command external/local_config_cuda/crosstool/clang/bin/crosstool_wrapper_driver_is_not_gcc @bazel-out/k8-opt/bin/modules/zj_prediction/hello-2.params
bazel-out/k8-opt/bin/modules/zj_prediction/_objs/hello/hello.o: In function `main':
hello.cc:(.text.startup.main+0x3c): undefined reference to `boost::python::api::object::object(boost::python::handle<_object> const&)'
hello.cc:(.text.startup.main+0x75): undefined reference to `boost::python::api::getattr(boost::python::api::object const&, char const*)'
hello.cc:(.text.startup.main+0xe8): undefined reference to `boost::python::throw_error_already_set()'
hello.cc:(.text.startup.main+0xf2): undefined reference to `boost::python::throw_error_already_set()'
hello.cc:(.text.startup.main+0x126): undefined reference to `vtable for boost::python::error_already_set'
hello.cc:(.text.startup.main+0x141): undefined reference to `boost::python::error_already_set::~error_already_set()'
hello.cc:(.text.startup.main+0x15f): undefined reference to `boost::python::error_already_set::~error_already_set()'
bazel-out/k8-opt/bin/modules/zj_prediction/_objs/hello/hello.o:(.data.rel.local.DW.ref._ZTIN5boost6python17error_already_setE[DW.ref._ZTIN5boost6python17error_already_setE]+0x0): undefined reference to `typeinfo for boost::python::error_already_set'
collect2: error: ld returned 1 exit status
看报错信息大概意思是boost找不到包里的Python库,为此上网找了一下午都没解决,后来突然发现是因为楼主的环境配置跟别人不一样,lib的名字不同当然不能直接复制解决了,下面说一下解决思路。
主要参考的是Add boost library as Bazel dependency c++ - Stack Overflow
Since you're linking your executable to Boost Python/Numpy, you also need to provide Python symbols.
If you don't need Python, the easiest solution is add
libboost_numpy.so
toexclude
in your glob. If you actually need Python, a quick fix would be to add-lpython
tolinkopts
inBOOST.build
(this is not a solution that I would recommend for production, since you have no control over Python versions, etc..)
里面提到要在 BOOST.build里面加入-lpython,
还有對boost::python::detail::init_module和 friend 的 undefined reference - C++ _程式人
我添加了兩個額外的標誌來增強效果,然後就可以了!
-lboost_python -lboost_system
里面提到加入的是-lboost_python,我两种都试了一下发现不行,于是开始思考人生。
先看下我的boost.BUILD文件是什么样的:
load("@rules_cc//cc:defs.bzl", "cc_library")
licenses(["notice"])
package(default_visibility = ["//visibility:public"])
# TODO(all): May use rules_boost.
cc_library(
name = "boost",
includes = ["."],
linkopts = [
"-L/opt/apollo/sysroot/lib",
"-lboost_filesystem",
"-lboost_program_options",
"-lboost_regex",
"-lboost_system",
"-lboost_thread",
# "-lboost_python36", 一开始没有
],
)
直接在linkopts里面加上这两种-l都没用,于是急需谷歌搜bazel cannot find -lboost_python,然后出现这一条:
https://stackoverflow.com/questions/65675412/bazel-build-cannot-find-shared-library,里面提到了-L/usr/local/lib
Bazel likes to use the gold linker instead of GNU ld by default. gold, unlike GNU ld, doesn't put
/usr/local/lib
on the default library search path. This can be remediated by passing--linkopt=-L/usr/local/lib
to Bazel.
然后猛然发现自己的boost.BUILD 文件里面有一行"-L/opt/apollo/sysroot/lib",这明显是跟上面提到的-L/usr/local/lib
起相同的作用,于是
ll /opt/apollo/sysroot/lib/
发现下面有很多libboost***,然后果然找到了一个
/opt/apollo/sysroot/lib/libboost_python36.so -> libboost_python36.so.1.74.0*
所以合理猜测在我的环境里,并不是 -lboost_python,而应该是 -lboost_python36!!!
在boost.BUILD文件里加入这行后,顺利编译成功,实现了C++调用Python输出
Hello, World