boa*_*001 5 c++ python swig iterator
Collection我有一个管理 a std::vector<Element>(该类的私有成员)的C++ 类。
在 C++ 中,我可以使用begin()和end()迭代器(它们只是vector's 迭代器的类型定义)来迭代向量,如下所示:
Collection col;
for (Collection::const_iterator itr = col.begin(); itr != col.end(); itr++)
{
std::cout << itr->get() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
现在我希望用 Python 做类似的事情,例如:
import example
el = example.Element()
el.set(5)
col = example.Collection()
col.add(el)
for e in col:
print e.get()
Run Code Online (Sandbox Code Playgroud)
但这会导致:
类型错误:“集合”对象不可迭代
我无法以生成__iter__Python 类(我认为这是它唯一需要的)的方式配置 SWIG Collection。我该怎么做?
这是我的代码:
示例.h:
#include <vector>
class Element
{
public:
Element();
~Element();
int get() const;
void set(const int var);
private:
int variable_;
};
class Collection
{
public:
Collection();
~Collection();
void add(const Element& element);
typedef std::vector<Element> tElements;
// iterators
typedef tElements::iterator iterator;
typedef tElements::const_iterator const_iterator;
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
private:
tElements elements_;
};
Run Code Online (Sandbox Code Playgroud)
示例.cpp:
#include "example.h"
Element::Element() {}
Element::~Element() {}
int Element::get() const
{
return variable_;
}
void Element::set(const int var)
{
variable_ = var;
}
Collection::Collection() : elements_() {}
Collection::~Collection() {}
void Collection::add(const Element& element)
{
elements_.push_back(element);
}
Collection::iterator Collection::begin()
{
return elements_.begin();
}
Collection::const_iterator Collection::begin() const
{
return elements_.begin();
}
Collection::iterator Collection::end()
{
return elements_.end();
}
Collection::const_iterator Collection::end() const
{
return elements_.end();
}
Run Code Online (Sandbox Code Playgroud)
示例.i:
%module example
%{
#include "example.h"
%}
// I've tried to add this, but that generates a whole
// other class, that is not what I want.
// %include "std_vector.i"
// %template(ElementVector) std::vector<Element>;
// I've also tried to %extend the class (which I think is what I want,
// but I cannot figure out with what to extend it with)
// Include the header file with above prototypes
%include "example.h"
Run Code Online (Sandbox Code Playgroud)
编译:
swig -python -c++ -o example_wrap.cpp example.i
g++ -fPIC -c example.cpp example_wrap.cpp -I/usr/include/python2.6
g++ -shared example.o example_wrap.o -o _example.so
Run Code Online (Sandbox Code Playgroud)
受到最后一个示例的启发:/sf/answers/617991811/。我想出了一种稍微不同的方法,它不使用变量来检查 StopIterator 异常状态。
此外,它仅使用 的begin()结束end()迭代器,Collection而不需要公开(make public)其std::vector<Element>自身。
示例.i:
%module example
%{
#include "example.h"
%}
%inline %{
class StopIterator {};
class Iterator {
public:
Iterator(Collection::iterator _cur, Collection::iterator _end) : cur(_cur), end(_end) {}
Iterator* __iter__()
{
return this;
}
Collection::iterator cur;
Collection::iterator end;
};
%}
%include "example.h"
%include "exception.i"
%exception Iterator::next {
try
{
$action // calls %extend function next() below
}
catch (StopIterator)
{
PyErr_SetString(PyExc_StopIteration, "End of iterator");
return NULL;
}
}
%extend Iterator
{
Element& next()
{
if ($self->cur != $self->end)
{
// dereference the iterator and return reference to the object,
// after that it increments the iterator
return *$self->cur++;
}
throw StopIterator();
}
}
%extend Collection {
Iterator __iter__()
{
// return a constructed Iterator object
return Iterator($self->begin(), $self->end());
}
};
Run Code Online (Sandbox Code Playgroud)
我唯一不明白的是如何创建一个模板化版本, Iterator以便我可以传递任何模板,Iterator<Collection, Element>而不必next()为每个模板实例重新定义。欢迎提供解决方案;)
| 归档时间: |
|
| 查看次数: |
2484 次 |
| 最近记录: |