【问题标题】:does boost python support a function returning a vector, by ref or value?boost python 是否支持通过引用或值返回向量的函数?
【发布时间】:2011-03-15 12:49:20
【问题描述】:

我是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 吗?

任何帮助表示赞赏。

头像

【问题讨论】:

    标签: boost-python


    【解决方案1】:

    Autopulated 的原因基本上是正确的,但代码比必要的复杂。

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

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

    还有一个 ma​​p_indexing_suite

    【讨论】:

      【解决方案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 的大量帮助。

      【讨论】:

        猜你喜欢
        • 2013-08-31
        • 2013-07-07
        • 1970-01-01
        • 2018-07-27
        • 1970-01-01
        • 2019-06-11
        • 2023-03-21
        • 2019-06-03
        • 1970-01-01
        相关资源
        最近更新 更多