boost::python:Python 列表到 std::vector

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3761391/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:36:26  来源:igfitidea点击:

boost::python: Python list to std::vector

pythonboostboost-pythonstdvector

提问by dmorlock

Finally I'm able to use std::vector in python using the [] operator. The trick is to simple provide a container in the boost C++ wrapper which handles the internal vector stuff:

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

#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)
    ;
 }

The other challenge is: Howto translate python lists into std::vectors? I tried to add a c++ class expecting a std::vector as parameter and added the corresponding wrapper code:

另一个挑战是:如何将 python 列表转换为 std::vectors?我尝试添加一个需要 std::vector 作为参数的 c++ 类并添加了相应的包装器代码:

#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)
    ;
 }

But if doing so, I end up with the following Boost.Python.ArgumentError:

但如果这样做,我最终会得到以下 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> >)

Can anybody tell me how I can access python lists within my c++ function?

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

Thanks, Daniel

谢谢,丹尼尔

采纳答案by Arlaharen

To make your C++ method accept Python lists you should use boost::python::list

要使您的 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]));
    }
}

回答by eudoxos

To get automatic conversion from python lists, you have to define a converter, which

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

  1. checks if the list is convertible to your type (i.e. that it is a sequence; additionally, you can also check whether all elements are of required type, but that can be handled in the second step as well)
  2. returns the new object, if the first step succeeded; throw exception if a sequence element is not convertible to what you need.
  1. 检查列表是否可转换为您的类型(即它是一个序列;此外,您还可以检查是否所有元素都是必需的类型,但这也可以在第二步中处理)
  2. 如果第一步成功,则返回新对象;如果序列元素无法转换为您需要的元素,则抛出异常。

I can't find now anything else than my code, you can copy&paste this template(it is specialized at the end of that file for various contained types).

除了我的代码之外,我现在找不到任何其他内容,您可以复制并粘贴此模板(它专门用于该文件的末尾,用于各种包含的类型)。

回答by rdesgroppes

Here's what I use:

这是我使用的:

#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 >( ) );
}

Should you find the input type (py::object) too liberal, feel free to specify stricter types (py::list in your case).

如果您发现输入类型 (py::object) 过于宽松,请随意指定更严格的类型(在您的情况下为 py::list)。

回答by Andreas Grivas

Based on the above answers I created an example of accessing python lists in C++ as well as returning a python list from a C++ function:

基于上述答案,我创建了一个在 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);
}

For a build example and a test python script take a look here

有关构建示例和测试 python 脚本,请查看此处

Thank you Arlaharen & rdesgroppes for the pointers (pun not intended).

谢谢 Arlaharen & rdesgroppes 的指点(不是双关语)。