C++封装python接口(libboost-python)
Posted SUN_DRAGON
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++封装python接口(libboost-python)相关的知识,希望对你有一定的参考价值。
摘要
在Python技术文档中可以找到关于Python与C++之间相互调用的部分。分别叫做extending和Embedding。可以参考技术文档Extending and Embedding the Python Interpreter。于此同时,还提供了 Python/C API接口Python/C API Reference Manual。虽然对于简单的调用使用起来很方便,但对于复杂的结构、封装和继承,操作较为复杂。因此本文介绍我在项目中使用了libboost-python来对C++进行封装Python接口的心得体会。libboost-python可以满足C++中所有的封装。
CMake配置
FIND_PACKAGE(Boost 1.59.0)
IF(Boost_FOUND)
include_directories($Boost_INCLUDE_DIRS ../venv/local/include/python2.7/ )
SET(Boost_USE_STATIC_LIBS OFF)
SET(Boost_USE_MULTITHREADED ON)
SET(Boost_USE_STATIC_RUNTIME OFF)
FIND_PACKAGE(Boost 1.59.0 COMPONENTS python)
ADD_LIBRARY(pyfaceos SHARED main.cpp faceos.cpp)
target_link_libraries(pyfaceos -ldl $Boost_LIBRARIES)
set_target_properties(pyfaceos PROPERTIES PREFIX “” OUTPUT_NAME “faceos”)
ELSEIF(NOT Boost_FOUND)
MESSAGE(FATAL_ERROR “Unable to find correct Boost version. Did you set BOOST_ROOT?”)
ENDIF()
声明库的名称
BOOST_PYTHON_MODULE(lib name)
类型映射
enum
enum_<Color>("Color")
.value("RED",RED)
.value("BLUE",BLUE)
.value("GREEN",GREEN)
.export_values();
class/struct
class_<rect>("rect")
.def_readwrite("left", &cv_rect_t::left)
.def_readwrite("top", &cv_rect_t::top)
.def_readwrite("right", &cv_rect_t::right)
.def_readwrite("bottom",&cv_rect_t::bottom)
.def("somefunc", &rect::somefunc) ;
参数当中如果存在引用,且引用之间或与返回值之间存在相互关系,需要增加调用策略。
封装容器
//定义容器封装模板
void IndexError() PyErr_SetString(PyExc_IndexError, "Index out of range");
template<class T>
struct std_item
typedef typename T::value_type V;
static V& get(T & x, int i)
if( i<0 ) i+=x.size();
if( i>=0 && i<x.size() )
//printf("in size\\n");
return x[i];
IndexError();
static void set(T & x, int i, V const& v)
if( i<0 ) i+=x.size();
if( i>=0 && i<x.size() ) x[i]=v;
else IndexError();
static void del(T & x, int i)
if( i<0 ) i+=x.size();
if( i>=0 && i<x.size() )
x.erase(x.begin() + i);
else
IndexError();
static void add(T & x, V const& v)
x.push_back(v);
;
//定义特定的类型
typedef vector<someclass> VecClass;
//定义接口
class_<VecClass>("VecClass")
.def("__len__", &VecClass::size)
.def("clear", &VecClass::clear)
.def("append", &std_item<VecClass>::add,
with_custodian_and_ward<1,2>()) // to let container keep value
.def("__getitem__", &std_item<someclass>::get,
return_value_policy<copy_non_const_reference>())
.def("__setitem__", &std_item<someclass>::set,
with_custodian_and_ward<1,2>()) // to let container keep value
.def("__delitem__", &std_item<someclass>::del);
类似地,可以使用这种方法来封装数组,list,map等。
对接ndarray
坑在之前的工作中,我想将一个ndarray参数传入到C++函数当中,之前使用numeric传入到C++之中,并利用num_util获得到数据内容。该库是对底层Python C API 的封装,但用起来很不方便。
仅使用numeric及boost-python对python对象的封装即可完成数据的传递和获取。
这里着重介绍ndarray的传递,其他可参加参见referrence mannul中的Object Wrappers部分。
//获取ndarray中的指针,容易用到
bp::str s = img.tostring();
char* c_str = bp::extract<char*>(s);
//得到形状
const bp::tuple &shape = bp::extract<bp::tuple>(img.attr("shape"));
int dims = bp::extract<int>(shape.attr("__len__")());
int height = bp::extract<int>(shape[0]);
int width = bp::extract<int>(shape[1]);
//访问单个数据
#include <boost/python/numeric.hpp>
#include <boost/python/tuple.hpp>
// sets the first element in a 2d numeric array
void set_first_element(numeric::array& y, double value)
y[make_tuple(0,0)] = value;
http://www.boost.org/doc/libs/1_61_0/libs/python/doc/html/tutorial/index.html
http://www.boost.org/doc/libs/1_61_0/libs/python/doc/html/
以上是关于C++封装python接口(libboost-python)的主要内容,如果未能解决你的问题,请参考以下文章