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

痴心易碎 提交于 2019-11-30 16:29:25

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.

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.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!