首页 文章

来自基类虚函数的Boost :: python和迭代器

提问于
浏览
2

所以我正在尝试编写一个基类来处理包装std :: vector的类,我已经开始定义__iter__函数 . 我的第一种方法,也是我希望工作的方法,是在基类中使用begin()和end()函数 . 这样编译很好,但是当我在python中运行代码时,我得到一个类似于以下内容的错误:

Boost.Python.ArgumentError:Container .__ iter __(Container)中的Python参数类型与C签名不匹配:__iter __(boost :: python :: back_reference <stl_iter <std :: vector <std :: shared_ptr <K>> std: :allocator <std :: shared_ptr <K >>>>&>)

可以使用以下示例扩展进行测试

from test import *

c = Container()

for i in range(10):
    c.append(K(str(i)))

for i in c:
    print i

示例扩展名:

#include <memory>
#include <vector>
#include <string>
#include <boost/python.hpp>

template<class T> 
T* get_pointer(std::shared_ptr<T> const& p) { return p.get(); }

template<class T>
class stl_iter {
protected:
    typedef typename T::value_type V;
    typedef typename T::iterator iter;
    virtual T& get_vector()=0;
public:
    virtual ~stl_iter() {}

    virtual void append(V item) {
        get_vector().push_back(item);
    }

    virtual iter begin() {
        return get_vector().begin();
    }

    virtual iter end() {
        return get_vector().end();
    }
};

class K {
    std::string val;
public:
    K(std::string s) : val(s) {}

    std::string get_val() const { return val; }
};
typedef std::shared_ptr<K> pK;
typedef std::vector<pK> vK;

class Container : public stl_iter<vK> {
    vK items;
protected:
    vK& get_vector() { return items; }

public:
    // Works if I uncomment these
    //vK::iterator begin() { return get_vector().begin(); }
    //vK::iterator end() { return get_vector().end(); }


public:
    virtual ~Container() {}
};
typedef std::shared_ptr<Container> pContainer;
typedef std::vector<pContainer> vContainer;

BOOST_PYTHON_MODULE_INIT(test) {
    using namespace boost::python;

    class_<K, pK>("K", init<std::string>())
        .def("__str__", &K::get_val)
        ;

    class_<Container, pContainer>("Container")
        .def("append", &Container::append)
        .def("__iter__", range(&Container::begin, &Container::end))
        ;
}

2 回答

  • 1

    答案实际上非常简单:使容器的行为类似于stl容器,然后使用boost的 iterator<>() 函数而不是 range() .

    为此,我必须将 stl_iter 中的typedef设为public,并将它们重命名为 value_typeiterator .

    下面是更新的C代码 .

    #include <memory>
    #include <vector>
    #include <string>
    #include <boost/python.hpp>
    
    template<class T> 
    T* get_pointer(std::shared_ptr<T> const& p) { return p.get(); }
    
    template<class T>
    class stl_iter {
    protected:
        virtual T& get_vector()=0;
    public:
        // Next two lines changed, and made public
        typedef typename T::value_type value_type;
        typedef typename T::iterator iterator;
    
        virtual ~stl_iter() {}
    
        virtual void append(value_type item) {
            get_vector().push_back(item);
        }
    
        virtual iterator begin() {
            return get_vector().begin();
        }
    
        virtual iterator end() {
            return get_vector().end();
        }
    };
    
    class K {
        std::string val;
    public:
        K(std::string s) : val(s) {}
    
        std::string get_val() const { return val; }
    };
    typedef std::shared_ptr<K> pK;
    typedef std::vector<pK> vK;
    
    class Container : public stl_iter<vK> {
        vK items;
    protected:
        vK& get_vector() { return items; }
    
    public:
        virtual ~Container() {}
    };
    typedef std::shared_ptr<Container> pContainer;
    typedef std::vector<pContainer> vContainer;
    
    BOOST_PYTHON_MODULE_INIT(test) {
        using namespace boost::python;
    
        class_<K, pK>("K", init<std::string>())
            .def("__str__", &K::get_val)
            ;
    
        class_<Container, pContainer>("Container")
            .def("append", &Container::append)
            // Use iterator() instead of range()
            .def("__iter__", iterator<Container>())
            ;
    }
    
  • 1

    range() 也可以使用,但底层迭代器无论如何应该支持STL语义,here is sample

    ...
    .def("__iter__"
         , range<return_value_policy<copy_non_const_reference> >(
               &my_sequence<heavy>::begin
             , &my_sequence<heavy>::end))
    

相关问题