编译运行Boost.Python的HelloWorld
2018-01-11 14:19:51 +08 字数:1578 标签: Python C对于C/C++开发经验不多、或者只有Python经验的人来说,要跑通一个Boost.Python的HelloWord程序,是一件不容易的事。 本文介绍如何避开bjam,用Makefile打通最不容易的那个环节——编译。
简介 ¶
Boost.Python是Boost项目的一部分,是一个C++写的库,用来提供Python调用C++代码的接口。
在Python中,直接使用C语言代码是很容易的,用ctypes即可。 而如果需要使用C++的类、对象、方法、虚函数等高级语言特性,则没那么简单。 Boost.Python通过简单的包装,就可以暴露C++接口给Python使用,支持多数常见的语言特性。
Tutorial ¶
如其Tutorial所述,其实Boost.Python的使用方式很简单。 写一个wrapper,即可提供给Python层调用。
#include <boost/python.hpp>
char const* greet()
{
return "hello, world";
}
BOOST_PYTHON_MODULE(hello_ext)
{
using namespace boost::python;
def("greet", greet);
}
编译以上文件(可命名为greet.c),即可在Python中使用。
>>> import hello_ext
>>> print hello_ext.greet()
hello, world
坑? ¶
Demo看上去似乎很简单,为什么是坑呢?
编译准备 ¶
首先,#include
那行就泄露了一点天机。
为了编译这个Demo文件,得安装libboost-all-dev。
这东西及其依赖,有好几百兆,得花不少准备时间。
另外还需python-dev或python3-dev。
sudo apt install libboost-all-dev python-dev python3-dev
当然,编译常用的gcc、make等组件(build-essential)必须提前具备。
(本文创作平台是Debian Stretch,Boost的版本是1.62.0.1,相关库为boost_python-py27、boost_python-py35。 Python的库是python2.7和python3.5m。)
编译 ¶
其次,编译仍然是个问题。
如果翻到文档的下一页,看到《Building Hello World》,初学者会更加不幸!
这不仅无助于解决问题,反而加剧了困惑。
不要指望能迅速从bjam
、Jamroot、Jamfile这个坑里出来,除非已经是资深的C++开发者。
如果实在是想跑通这个HelloWorld,可以尝试以下的Makefile。
hello_ext.so : greet.o
g++ -shared greet.o -o hello_ext.so -lpython2.7 -lboost_python
greet.o : greet.cpp
g++ -c -fPIC -O2 -I/usr/include/python2.7 greet.cpp -o greet.o
把以上代码,写入同目录的Makefile文件。 并且按照以下步骤执行,可以成功看到Boost.Python的效果。
$ make
g++ -c -fPIC -O2 -I/usr/include/python2.7 greet.cpp -o greet.o
g++ -shared greet.o -o hello_ext.so -lpython2.7 -lboost_python
$ ipython2
>>> import hello_ext
>>> print hello_ext.greet()
hello, world
以上是Python 2.7的例子,因为-lboost_python
默认是Python 2.x的。
以下再给出一个Python 3.5的Makefile。
hello_ext.so : greet.o
g++ -shared greet.o -o hello_ext.so -lpython3.5m -lboost_python-py35
greet.o : greet.cpp
g++ -c -fPIC -I/usr/include/python3.5m greet.cpp -o greet.o
这个Makefile中记录的每一个g++
参数都是必须的,连文件命名都不能乱改,一点微调都会走样。
其中有许多深坑,就不一一介绍了。
总结 ¶
和ctypes的直接可用相比,Boost.Python是一个略显复杂的方案。 不过在某些必须直接调用C++代码的情况下,它可以取代ctypes。 可以说,Boost.Python的适用性远在ctypes之上。
ctypes是以动态链接的方式使用libxxx.so,而Boost.Python是直接import写好的xxx.so。
不过,Boost.Python需要一个额外的C++包装层,并且在编译时还需要很多额外依赖。
此外,对开发者的C/C++开发实力,尤其是用gcc
编译、链接的能力,也有较高的要求。
所以,开发效率和发布时的通用性,比标准库ctypes差很多。
还是优先用ctypes吧,不行再来Boost.Python里想办法。
参考 ¶
Boost.Python在GitHub上的项目主页:https://github.com/boostorg/python