|
Boost : |
Subject: [boost] [python] non-standard iteration / wrapping member function return value
From: Matus Chochlik (chochlik_at_[hidden])
Date: 2013-06-04 13:07:47
Hi,
I'm stuck at trying to make python bindings for a set of classes that use a
non-c++-standard iteration protocol. I've made a minimal example of what
I'm trying to do:
the python-ized classes look in essence like this:
//-------------------------------------------------------------
class int_range
{
private:
int i, max;
public:
int_range(int m) : i(0), max(m) { }
bool empty(void) const { return i > max; }
int front(void) const { return i; }
void next(void) { ++i; }
};
class range_maker
{
public:
int_range make(void) const { return int_range(10); }
};
//-------------------------------------------------------------
the boost.python module that I've come up with so far:
//-------------------------------------------------------------
using namespace boost::python;
class _py_int_range_iter
{
private:
int_range _range;
public:
_py_int_range_iter(int_range range) : _range(range) { }
_py_int_range_iter self(void) { return *this; }
int next(void)
{
if(_range.empty())
objects::stop_iteration_error();
int result = _range.front();
_range.next();
return result;
}
};
class_<_py_int_range_iter>("_py_int_range_iter", init<const int_range&>())
.def("self", &_py_int_range_iter::self)
.def("next", &_py_int_range_iter::next)
;
class _py_int_range
{
private:
int_range _range;
public:
_py_int_range(int_range range) : _range(range) { }
_py_int_range_iter iter(void)
{
return _py_int_range_iter(_range);
}
};
class_<_py_int_range>("_py_int_range", init<const int_range&>())
.def("__iter__", &_py_int_range::iter)
;
//-------------------------------------------------------------
the problem is that when I register range_maker as follows...
//-------------------------------------------------------------
class_<range_maker>("range_maker")
.def("make", &range_maker::make)
;
//-------------------------------------------------------------
... it compiles but (obviously) fails in python at run-time because
range_maker::make returns int_range and not _py_int_range.
what do I need to do to make this work?
I know that I could write _py_range_maker wrapping range_maker and let it
return _py_int_range, but this approach does not scale very well.
Is there some way to tell the def(...) function that I want to wrap the
return value into an object of another type? Is there a return value policy
for that or do I need to write my own? If so how?
Thanks in advance
Matus
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk