Re: [C++-sig] boost.python iterators
Dirk, you're in the wrong mailing list/newsgroup. Try the Python C++ sig (where followups are directed). Dirk Steenpass <steenpaz@sdf-eu.org> writes:
Dear all,
I am looking for a way to create a python savvy iterator by wrapping a container that provides begin and end member functions taking arguments.
Taking arguments, hmm.
The reference manual entry on boost::python::range left me unsure whether the appended code would compile (it does not).
The sentence:
"The first form creates a Python callable object which, when invoked, converts its argument to a Target object x, and creates a Python iterator which traverses [bind(start,_1)(x), bind(finish,_1)(x)), applying NextPolicies to the iterator's next() function."
suggested to me that a single argument, i.e., the target reference is passed to the accessor functions.
Correct.
This would imply that the accessor takes exactly one argument. (???)
Correct.
However, the subsequent explanations about the deduction of Target left me with the impression that accessor functions and accessor member function pointers may take several arguments.
I understand. I think the text is misleading. I should delete "arguments..."
Any help is appreciated,
Your problem is that you're forgetting the implicit "this" argument. In Python that corresponds to the initial explicit "self." Probably your simplest solution would be something like: python::object Elements(A& a, A::SizeType n) { return python::range<python::default_call_policies, A>( boost::bind(&A::begin, _1, n) , boost::bind(&A::end, _1, n) )(boost::ref(a)); } Then wrap that. We create a new Python function object on the fly each time and invoke it. The bind expressions just bind n into the accessors so that they take only a single argument. HTH,
dirk
//--- A [n] example ----------------------------------------------------------- // Does not compile with gcc 3.3.6 and gcc 4.0.2
#include <vector>
#include <boost/python.hpp>
using namespace std; using namespace boost::python;
class A { public: typedef std::vector<int> VecInt; typedef VecInt::iterator Iter; typedef VecInt::size_type SizeType;
public: A(): vec_(100, 23) {}
Iter Begin(SizeType ignored) { return vec_.begin(); } Iter End(SizeType ignored) { return vec_.end(); }
private: VecInt vec_; };
BOOST_PYTHON_MODULE(A) { class_<A>("A") .def("Elements", range(&A::Begin, &A::End)) ; }
// Just allowing standalone compilation. int main(void) { return 0; }
-- Dave Abrahams Boost Consulting www.boost-consulting.com
On Mon, 15 Aug 2005 22:35:45 -0400, David Abrahams wrote:
Dirk, you're in the wrong mailing list/newsgroup. Try the Python C++ sig (where followups are directed).
Sorry. [snip]
Probably your simplest solution would be something like:
python::object Elements(A& a, A::SizeType n) { return python::range<python::default_call_policies, A>( boost::bind(&A::begin, _1, n) , boost::bind(&A::end, _1, n) )(boost::ref(a)); }
Then wrap that. We create a new Python function object on the fly each time and invoke it. The bind expressions just bind n into the accessors so that they take only a single argument.
HTH,
Yep, that is neat and works. Though the default_call_policies cannot be used as the wrapped iterator returns by reference. Thx, dirk [snip] -- Dirk Steenpass
Dirk Steenpass <steenpaz@sdf-eu.org> writes:
Yep, that is neat and works. Though the default_call_policies cannot be used as the wrapped iterator returns by reference.
That is not a foregone conclusion, but it may be true in your case. -- Dave Abrahams Boost Consulting www.boost-consulting.com
On Tue, 16 Aug 2005 09:05:47 -0400, David Abrahams wrote:
Dirk Steenpass <steenpaz@sdf-eu.org> writes:
Yep, that is neat and works. Though the default_call_policies cannot be used as the wrapped iterator returns by reference.
That is not a foregone conclusion, but it may be true in your case.
I try to be more precise: the default_call_policies will work for wrapped iterators that return non-pointer types, char const*, and PyObject* by value. Or putting it differently, functions that return references (aka automatically dereferenced pointer types) are not accepted by default_call_policies. Thus the following snippet is not supposed to compile (and does not do so): //------------------------------------------- // default_call_policies #include <boost/python.hpp> class Coo { public: Coo(int x): c_(x) {} int const& get_c() const { return c_; } private: int c_; }; using namespace boost::python; BOOST_PYTHON_MODULE(coo) { class_<Coo>("Coo", init<int>()) // Fails because of bad call policy. .def("get_c", &Coo::get_c, default_call_policies()) ; } int main(void) { return 0; } //------------------------------------------- I'm rather tenacious on the topic because the behavior of another call policy, namely return_internal_reference, keeps confusing me; most likely because I miss some important point about call policies in general. The following snippet illustrates that return_internal_reference can be used for a simple user defined type but not for the fundamental int. I am probably making a fool of myself, but I do not see why this is so. I am using boost-1.33.0. As usual, looking for enlightenment, dirk //------------------------------------------ // return_internal_reference #include <boost/python.hpp> struct C { C(int x): c_(x) {} int c_; }; class B { public: B(int x) : b_(x), c_(x) {} int const& get_b() const { return b_; } C const& get_c() const { return c_; } private: int b_; C c_; }; using namespace boost::python; BOOST_PYTHON_MODULE(b) { class_<B>("B", init<int>()) // Fundamental type, cannot be returned // by reference this way. .def("get_b", &B::get_b, return_internal_reference<>()) // User defined type: compiles fine. .def("get_c", &B::get_c, return_internal_reference<>()) ; } int main(void) { return 0; }
[snip]
The following snippet illustrates that return_internal_reference can be used for a simple user defined type but not for the fundamental int. [snip]
Probably, because it makes no sense to return an immutable object by reference... (fool, indeed ;-). cheers, dirk
participants (2)
-
David Abrahams -
Dirk Steenpass