does boost python support a function returning a vector, by ref or value?

后端 未结 2 1890
半阙折子戏
半阙折子戏 2021-01-03 12:53

I am new to python, I have looked at boost python, and it looks very impressive. However going through the introduction I can not find any examples where, vector of objects

相关标签:
2条回答
  • 2021-01-03 13:43

    Because you can't expose template types to python you have to explicitly expose each sort of vector that you want to use, for example this is from my code:

    Generic template to wrap things:

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

    Then, for each container:

        // 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 > >())
        ;
        // ... 
    

    A similar approach is possible for std::map. I used lots of help from wiki.python.org when writing this.

    0 讨论(0)
  • 2021-01-03 13:59

    Autopulated's reason was essentially correct, but the code was more complicated then necessary.

    The vector_indexing_suite can do all that work for you:

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

    There is a map_indexing_suite as well.

    0 讨论(0)
提交回复
热议问题