2010-09-21 75 views
20

最后,我可以使用[]运算符在python中使用std :: vector。诀窍是简单的在处理内部向量东西升压C++包装提供了一个容器:boost :: python:python list to std :: vector

#include <boost/python.hpp> 
#include <vector> 
class world 
{ 
    std::vector<double> myvec; 

    void add(double n) 
    { 
     this->myvec.push_back(n); 
    } 

    std::vector<double> show() 
    { 
    return this->myvec; 
    } 
}; 

BOOST_PYTHON_MODULE(hello) 
{ 
    class_<std::vector<double> >("double_vector") 
     .def(vector_indexing_suite<std::vector<double> >()) 
    ; 

    class_<World>("World") 
    .def("show", &World::show) 
     .def("add", &World::add) 
    ; 
} 

另一个挑战是:HOWTO Python列表转换成标准::载体?我尝试添加C++类期待一个std ::向量作为参数,并加入相应的包装代码:

#include <boost/python.hpp> 
#include <vector> 
class world 
{ 
    std::vector<double> myvec; 

    void add(double n) 
    { 
     this->myvec.push_back(n); 
    } 

    void massadd(std::vector<double> ns) 
    { 
     // Append ns to this->myvec 
    } 

    std::vector<double> show() 
    { 
    return this->myvec; 
    } 
}; 

BOOST_PYTHON_MODULE(hello) 
{ 
    class_<std::vector<double> >("double_vector") 
     .def(vector_indexing_suite<std::vector<double> >()) 
    ; 

    class_<World>("World") 
    .def("show", &World::show) 
     .def("add", &World::add) 
     .def("massadd", &World::massadd) 
    ; 
} 

但是,如果这样做,我结束了以下Boost.Python.ArgumentError:

>>> w.massadd([2.0,3.0]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
Boost.Python.ArgumentError: Python argument types in 
    World.massadd(World, list) 
did not match C++ signature: 
    massadd(World {lvalue}, std::vector<double, std::allocator<double> >) 

有人能告诉我如何在我的C++函数中访问python列表吗?

感谢, 丹尼尔

回答

23

为了让你的C++方法接受Python列表,你应该使用boost::python::list

void massadd(boost::python::list& ns) 
{ 
    for (int i = 0; i < len(ns); ++i) 
    { 
     add(boost::python::extract<double>(ns[i])); 
    } 
} 
+0

'boost :: python :: list'可以是异构的,你也可以从'extract'中捕获异常。 – eudoxos 2011-08-10 08:08:01

+0

我的道歉,'extract'的异常将自动转换为python。抱歉。 – eudoxos 2011-08-12 12:30:58

+4

是啊,很好,很简单,只是提升python文档是如此之差,并且operator []隐藏在一个模板object_operators层次上的几个层次,而不是明显的操作列表。我还没有发现他们的网站文档更友好。 使len()成为外部方法并不像他们认为的那样酷。 Plus是否是迭代的唯一方法? – CashCow 2012-12-17 11:00:27

1

要想从Python列表自动转换,你必须定义一个转换器,它

  1. 检查列表是否可以转换为您的类型(即,它是一个序列;此外,您还可以检查是否所有元素都是重新但是可以在第二步中处理)
  2. 返回新对象,如果第一步成功;如果序列元素不能转换为您需要的,则抛出异常。

我现在找不到什么比我的代码一样,你可以复制粘贴& this template(它是专门在该文件中的各种所含类型的结束)。

17

下面是我用什么:

#include <boost/python/stl_iterator.hpp> 

namespace py = boost::python; 

template< typename T > 
inline 
std::vector<T> to_std_vector(const py::object& iterable) 
{ 
    return std::vector<T>(py::stl_input_iterator<T>(iterable), 
          py::stl_input_iterator<T>()); 
} 

,你应该找到输入型(PY ::对象)过于宽松,随意(在你的情况PY ::列表)来指定严格的类型。

3

基于我创建访问用C Python列表++以及从C返回Python列表++函数的例子在上述的答案:

#include <boost/python.hpp> 
#include <string> 

namespace py = boost::python; 

// dummy class 
class drow{ 
    public: 
     std::string word; 
     drow(py::list words); 
     py::list get_chars(); 
}; 

// example of passing python list as argument (to constructor) 
drow::drow(py::list l){ 
    std::string w; 
    std::string token; 
    for (int i = 0; i < len(l) ; i++){ 
     token = py::extract<std::string>(l[i]); 
     w += token; 
    } 
    this -> word = w; 
} 

// example of returning a python list 
py::list drow::get_chars(){ 
    py::list char_vec; 
    for (auto c : word){ 
     char_vec.append(c); 
    } 
    return char_vec; 
} 

// binding with python 
BOOST_PYTHON_MODULE(drow){ 
    py::class_<drow>("drow", py::init<py::list>()) 
     .def("get_chars", &drow::get_chars); 
} 

对于一个构建实例和测试Python脚本来看看here

谢谢Arlaharen & rdesgroppes为指针(双关语没有打算)。