Boost与Python 3.x
boost.python是怎么处理Python 3的?它只支持Python 2吗?
8 个回答
是的,这个问题很老了,但我做了一些这里的答案没有提到的事情(虽然是基于一些建议的),所以我快速记录一下我的整个过程:
- 下载 boost_X_Y_Z.tar.bz2(我用的是 boost 1.68.0)
tar --bzip2 -xf boost_1_68_0.tar.bz2
(在你想临时放这个文件夹的地方)cd boost_1_68_0
./bootstrap.sh --with-python-version=3.6 --prefix=/usr/local
./b2
sudo ./bjam install
cp tools/build/example/user-config.jam $HOME
,然后修改这个文件的内容,改成using python : 3.6 : /usr/bin/python3 : /usr/include/python3.6m : /usr/lib ;
(或者根据你的环境修改成合适的文件夹)
给定这个 C++ 源文件 BoostPythonHelloWorld.cpp
:
#include <boost/python.hpp>
char const* say_hi()
{
return "Hi!";
}
BOOST_PYTHON_MODULE(BoostPythonHelloWorld)
{
boost::python::def("say_hi", say_hi);
}
还有这个 Python 脚本 BoostPythonHelloWorld.py
:
import BoostPythonHelloWorld
print(BoostPythonHelloWorld.say_hi())
可以这样编译和运行:
gcc -c -fPIC -I/path/to/boost_1_68_0 -I/usr/include/python3.6 /other_path/to/BoostPythonHelloWorld.cpp
gcc -shared -Wall -Werror -Wl,--export-dynamic BoostPythonHelloWorld.o -L/path/to/boost_1_68_0/stage/lib -lboost_python36 -o BoostPythonHelloWorld.so
python3 BoostPythonHelloWorld.py
对我来说不同的地方是 -Wl,--export-dynamic BoostPythonHelloWorld.o
,我之前没有见过这个,直到我加上它,我才解决了一个关于未定义符号的 Python 错误。
希望这对将来某个人有帮助!
要实现这个功能,libboostpython 需要用 python3 来构建。但是,这在 boost 1.58 版本上是行不通的(这个版本是 Ubuntu 16.04 自带的),所以一定要下载最新的 boost 版本。我刚刚使用的是 boost_1_64_0。
如上所述,找到你 boost 代码包中的 "user-config.jam" 文件,并把它复制到 $HOME 目录。
cp /path/to/boost_1_64_0/tools/build/example/user-config.jam $HOME
然后编辑最后一行的 python 设置,使其变成:
using python : 3.5 : /usr/bin/python3 : /usr/include/python3.5m : /usr/lib ;
这个设置在 Ubuntu 16.04 上是正确的。你可以用 pkg-config 来找到正确的包含目录。
user@computer > pkg-config --cflags python3
-I/usr/include/python3.5m -I/usr/include/x86_64-linux-gnu/python3.5m
而且你只需要第一个包含目录。
接下来,从头开始构建 boost。(抱歉。)我把它安装到 /usr/local。
cd /path/to/boost_1_64_0
./bootstrap.sh --prefix=/usr/local
./b2
sudo ./b2 install
现在进入 python 示例目录,构建教程。
cd /path/to/boost_1_64_0/libs/python/example/tutorial
bjam
如果你的系统上已经安装了 boost,这个构建可能会失败,因为在后台,bjam 正在用 g++ 参数 "-lboost" 来链接 libboostpython。但在 Ubuntu 16.04 上,这样会直接找到 "/usr/lib/x86_64-linux-gnu/libboost_python-py27.so.1.58.0",然后 python 绑定就会加载失败。实际上,你会看到这个错误:
ImportError: /usr/lib/x86_64-linux-gnu/libboost_python-py27.so.1.58.0: undefined symbol: PyClass_Type
如果你想查看 bjam 使用的 g++ 命令,可以这样做:
user@computer > bjam -d2 -a | grep g++
g++ -ftemplate-depth-128 -O0 -fno-inline -Wall -g -fPIC -I/usr/include/python3.5m -c -o "hello.o" "hello.cpp"
g++ -o hello_ext.so -Wl,-h -Wl,hello_ext.so -shared -Wl,--start-group hello.o -Wl,-Bstatic -Wl,-Bdynamic -lboost_python -ldl -lpthread -lutil -Wl,--end-group
这里我们看到了问题,你需要在 "-lboost_python" 之前加上 "-L/usr/includ/lib"。所以执行这个命令来正确链接共享库:
g++ -o hello_ext.so -Wl,-h -Wl,hello_ext.so -shared -Wl,--start-group hello.o -Wl,-Bstatic -Wl,-Bdynamic -L/usr/local/lib -lboost_python -ldl -lpthread -lutil -Wl,--end-group
你可能需要重新运行 ldconfig(或者重启一下)。
sudo ldconfig
现在你终于可以开始了:
user@computer > python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import hello_ext
>>> hello_ext.greet()
'hello, world'
>>> exit()
更新版的Boost应该可以很好地和Python V3.x一起使用。这项支持早在很久之前就已经添加了,我记得是在2009年一个成功的谷歌暑期编程项目之后。
要让Boost和Python V3一起使用,你需要正确配置构建系统,比如在你的user-config.jam文件中添加以下内容:
using python : 3.1 : /your_python31_root ;
。