I have a C++ class Collection
that manages a std::vector<Element>
(a private member of the class).
From C++ I can iterate through the vector using the begin()
and end()
iterators (which are just typedefs for the vector
's iterators) like:
Collection col;
for (Collection::const_iterator itr = col.begin(); itr != col.end(); itr++)
{
std::cout << itr->get() << std::endl;
}
Now I wish to do a similar thing from Python like:
import example
el = example.Element()
el.set(5)
col = example.Collection()
col.add(el)
for e in col:
print e.get()
But this results in:
TypeError: 'Collection' object is not iterable
I am not able to configure SWIG in a way that it generates the __iter__
(I think it's the only thing it needs) for the Python Collection
class. How am I supposed to do this?
This is my code:
example.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_;
};
example.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();
}
example.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"
Compile with:
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