C++封装python接口(libboost-python)

4 篇文章 0 订阅

摘要

在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/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值