32

最后,我可以使用 [] 运算符在 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)
    ;
 }

另一个挑战是:如何将 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)
    ;
 }

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

谢谢,丹尼尔

4

4 回答 4

32

要使您的 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]));
    }
}
于 2010-09-21T14:51:30.677 回答
27

这是我使用的:

#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::object) 过于自由,请随意指定更严格的类型(在您的情况下为 py::list)。

于 2013-09-30T10:35:54.817 回答
4

基于上述答案,我创建了一个在 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 脚本,请查看此处

感谢 Arlaharen 和 rdesgroppes 的指点(双关语不是有意的)。

于 2015-02-13T16:28:47.323 回答
2

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

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

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

于 2011-08-10T08:16:24.273 回答