2

我是 python 新手,我看过 boost python,它看起来非常令人印象深刻。但是通过介绍我找不到任何示例,其中对象向量作为python列表/元组返回。

即举这个例子,我想暴露类X,Cont及其所有功能。关键位将 X 或字符串的向量返回给 python

  class X {};

   class Cont {

       .....
       // how can this be exposed using boost python
       const std::vector<X>&  const_ref_x_vec() const { return x_vec_;}
       std::vector<X> value_x_vec() const { return x_vec;}

       const std::vector<std::string>& const_ref_str_vec() const { return str_vec_;}
       std::vector<std::string> value_str_vec() const { return str_vec_; }

       ...
   private:
       std::vector<X> x_vec_;
       std::vector<std::string> str_vec_;
  };

我自己试图公开 const_ref_x_vec()、value_x_vec() 等函数的尝试徒劳无功,只会导致编译错误。

从谷歌搜索中,我没有看到任何支持按值或引用返回向量的示例。这甚至可以通过 boost python 实现吗?有什么解决方法吗?我应该在这种情况下使用 SWIG 吗?

任何帮助表示赞赏。

阿凡达

4

2 回答 2

10

Autopulated 的理由基本上是正确的,但代码比必要的复杂得多。

vector_indexing_suite可以为您完成所有工作:

class_< std::vector<X> >("VectorOfX")
    .def(vector_indexing_suite< std::vector<X> >() )
    ;

还有一个map_indexing_suite

于 2010-11-09T20:45:08.707 回答
2

因为您不能将模板类型公开给 python,所以您必须显式公开您想要使用的每种向量,例如这是来自我的代码:

用于包装事物的通用模板:

namespace bp = boost::python;

inline void IndexError(){
    PyErr_SetString(PyExc_IndexError, "Index out of range");
    bp::throw_error_already_set();
}

template<class T>
struct vec_item{
    typedef typename T::value_type V;
    static V& get(T& x, int i){
        static V nothing;
        if(i < 0) i += x.size();
        if(i >= 0 && i < int(x.size())) return x[i];
        IndexError();
        return nothing;
    }
    static void set(T& x, int i, V const& v){
        if(i < 0) i += x.size();
        if(i >= 0 && i < int(x.size())) x[i] = v;
        else IndexError();
    }
    static void del(T& x, int i){
        if(i < 0) i += x.size();
        if(i >= 0 && i < int(x.size())) x.erase(x.begin() + i);
        else IndexError();
    }
    static void add(T& x, V const& v){
        x.push_back(v);
    }
};

然后,对于每个容器:

    // STL Vectors:
    // LineVec
    bp::class_< std::vector< Line > >("LineVec")
        .def("__len__", &std::vector< Line >::size)
        .def("clear", &std::vector< Line >::clear)
        .def("append", &vec_item< std::vector< Line > >::add, 
              bp::with_custodian_and_ward<1, 2>()) // let container keep value
        .def("__getitem__", &vec_item< std::vector< Line > >::get,
             bp::return_value_policy<bp::copy_non_const_reference>())
        .def("__setitem__", &vec_item< std::vector< Line > >::set,
             bp::with_custodian_and_ward<1,2>()) // to let container keep value
        .def("__delitem__", &vec_item< std::vector< Line > >::del)
        .def("__iter__", bp::iterator< std::vector< Line > >())
    ;
    // ... 

类似的方法是可能的std::map。在写这篇文章时,我使用了来自wiki.python.org的大量帮助。

于 2010-07-31T13:26:32.703 回答