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 に答える