在python中调用c++
c++ 速度快,python 比较方便,如果同时用到python和c++中库,则需要相互调用。目前python发展迅速,很多新库都以python为主,但一些传统或者强调速度的库依然是用c++写的。因此掌握这一技能,可以加速开发,避免重复地制造车轮。
介绍
在python中调用c++的方法很多,出名的有swig, boost.python,个人属于刚入门,由于对boost库有好感,觉得代表着c++方面最先进的技术。boost.python的理念也很好,不用去学习接口语言,不用修改源代码,直接快速上手。
官方文档
写一个小测试
- cpp.cpp: c++源文件
- py.py: python 测试文件
- Jamroot: boost.python 配置文件
安装boost环境
sudo apt-get install libboost-all-dev
再下载一个boost 源代码,这样可以进行下面的官方测试并得到配置文件Jamroot
官方测试
- hello world
cd /home/yzbx/Downloads/boost_1_61_0/libs/python/example/tutorial
bjam
warning: mismatched versions of Boost.Build engine and core
warning: Boost.Build engine (bjam) is 2014.03.00
warning: Boost.Build core (at /media/yzbx/NewPartition/home/yzbx/Downloads/boost_1_61_0/tools/build/src) is 2015.07-git
notice: no Python configured in user-config.jam
notice: will use default configuration
warning: No toolsets are configured.
warning: Configuring default toolset "gcc".
warning: If the default is wrong, your build may not work correctly.
warning: Use the "toolset=xxxxx" option to override our guess.
warning: For more configuration options, please consult
warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html
Performing configuration checks
- 32-bit : no (cached)
- 64-bit : yes (cached)
- arm : no (cached)
- mips1 : no (cached)
- power : no (cached)
- sparc : no (cached)
- x86 : yes (cached)
- symlinks supported : yes (cached)
...patience...
...patience...
...found 1833 targets...
python hello.py
hello, world
- 官方测试目录,输出一大堆如
bin,xxx.so
$: tree /home/yzbx/Downloads/boost_1_61_0/libs/python/example/tutorial
/home/yzbx/Downloads/boost_1_61_0/libs/python/example/tutorial
├── bin
│ ├── config.log
│ ├── gcc-5.4.0
│ │ └── debug
│ │ ├── hello_ext.so
│ │ └── hello.o
│ ├── hello.test
│ │ └── gcc-5.4.0
│ │ └── debug
│ │ ├── hello
│ │ ├── hello.output
│ │ └── hello.test
│ └── project-cache.jam
├── hello.cpp
├── hello_ext.so
├── hello.py
├── Jamroot
├── libboost_python.so -> libboost_python.so.1.61.0
├── libboost_python.so.1 -> libboost_python.so.1.61.0
├── libboost_python.so.1.61 -> libboost_python.so.1.61.0
└── libboost_python.so.1.61.0
- 上面的命令运行成功,说明安装boost.python环境成功!
在ubuntu16.04上基于官方测试进行更改
- struct or class ? 写c++一般用class,不过用class就要加public,否则默认为private就无法在python中调用。
- bjam 如何使用配置?
Simply copy the file and tweak use-project boost to where your boost root directory is and you're OK.
The comments contained in the Jamrules file above should be sufficient to get you going.
上面说只要指定boost的根目录,再按Jamroot中的注释去更改就okay!
3. 如上图,在个人测试文件夹下有三个文件:cpp.cpp,py.py,Jamroot
,将root根目录设置为/home/yzbx/Downloads/boost_1_61_0, 再将python 模块名改为yzbx_ext,再将源文件和测试文件改为cpp.cpp,py.py, 并将测试输出目录改为yzbx
4. 个人测试文件的输出,通过对比,不难了解各个参数的含义
$: tree ~/test/boost-python/
/home/yzbx/test/boost-python/
├── bin
│ ├── config.log
│ ├── gcc-5.4.0
│ │ └── debug
│ │ ├── cpp.o
│ │ └── yzbx_ext.so
│ ├── project-cache.jam
│ └── yzbx.test
│ └── gcc-5.4.0
│ └── debug
│ ├── yzbx
│ ├── yzbx.output
│ └── yzbx.test
├── cpp.cpp
├── Jamroot
├── libboost_python.so -> libboost_python.so.1.61.0
├── libboost_python.so.1 -> libboost_python.so.1.61.0
├── libboost_python.so.1.61 -> libboost_python.so.1.61.0
├── libboost_python.so.1.61.0
├── py.py
└── yzbx_ext.so
附件
cpp.cpp
// Copyright Joel de Guzman 2002-2004. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Hello World Example from the tutorial
// [Joel de Guzman 10/9/2002]
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
char const* greet()
{
return "hello, world";
}
int add(int a,int b){
return a+b;
}
struct bgs{
void set(int a){this->a=a;}
int getA(){return a;}
int a;
};
class Var
{
public:
Var(std::string name) : name(name), value() {}
std::string const name;
float value;
};
BOOST_PYTHON_MODULE(yzbx_ext)
{
using namespace boost::python;
def("greet", greet);
def("add",add);
class_<bgs>("bgs")
.def("set",&bgs::set)
.def("getA",&bgs::getA)
.def_readonly("a",&bgs::a)
;
class_<Var>("Var", init<std::string>())
.def_readonly("name", &Var::name)
.def_readwrite("value", &Var::value);
}
py.py
# Copyright Joel de Guzman 2002-2007. Distributed under the Boost
# Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt
# or copy at http://www.boost.org/LICENSE_1_0.txt)
# Hello World Example from the tutorial
import yzbx_ext
print yzbx_ext.greet()
print yzbx_ext.add(3,5)
bgs=yzbx_ext.bgs()
bgs.set(10)
print bgs.getA()
var=yzbx_ext.Var("pi")
var.value=3.14
print var.name,' is around ', var.value
Jamroot
# Copyright David Abrahams 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import python ;
if ! [ python.configured ]
{
ECHO "notice: no Python configured in user-config.jam" ;
ECHO "notice: will use default configuration" ;
using python ;
}
# Specify the path to the Boost project. If you move this project,
# adjust this path to refer to the Boost root directory.
use-project boost
: /home/yzbx/Downloads/boost_1_61_0 ;
# Set up the project-wide requirements that everything uses the
# boost_python library from the project whose global ID is
# /boost/python.
project
: requirements <library>/boost/python//boost_python
<implicit-dependency>/boost//headers
: usage-requirements <implicit-dependency>/boost//headers
;
# Declare the three extension modules. You can specify multiple
# source files after the colon separated by spaces.
python-extension yzbx_ext : cpp.cpp ;
# Put the extension and Boost.Python DLL in the current directory, so
# that running script by hand works.
install convenient_copy
: yzbx_ext
: <install-dependencies>on <install-type>SHARED_LIB <install-type>PYTHON_EXTENSION
<location>.
;
# A little "rule" (function) to clean up the syntax of declaring tests
# of these extension modules.
local rule run-test ( test-name : sources + )
{
import testing ;
testing.make-test run-pyd : $(sources) : : $(test-name) ;
}
# Declare test targets
run-test yzbx : yzbx_ext py.py ;