所以我正在尝试编写一个基类来处理包装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 回答
答案实际上非常简单:使容器的行为类似于stl容器,然后使用boost的
iterator<>()
函数而不是range()
.为此,我必须将
stl_iter
中的typedef设为public,并将它们重命名为value_type
和iterator
.下面是更新的C代码 .
range()
也可以使用,但底层迭代器无论如何应该支持STL语义,here is sample: