diff --git a/doc/special.html b/doc/special.html index 7debc7c1..73e96c26 100644 --- a/doc/special.html +++ b/doc/special.html @@ -657,7 +657,7 @@ for i in S: for (iterator i = S.begin(), end = S.end(); i != end; ++i) -
One could try to wrap C++ iterators in order to carry the C++ idiom into +
One could try to wrap C++ iterators directly in order to carry the C++ idiom into Python. However, this does not work very well because
- It is a better idea to support the standard Python
- sequence and mapping protocols for your wrapped containers. These
- operators have to be wrapped manually because there are no corresponding
+ Therefore, BPL provides a special helper class "cursor" that acts as
+ an adapter for STL iterators and enables them to be used within
+ normal Python loops. Suppose, for example, that we want to wrap a
+ std::list<BigNum>. First, we have to wrap this class itself,
+ as usual:
+
+
+ + Since+// wrap an STL conforming container +boost::python::class_builder<std::list<BigNum> > bignum_list_class(my_module, "BigNumList"); + +bignum_list_class.def(boost::python::constructor<>()); + +bignum_list_class.def((void (std::list<BigNum>::*)(BigNum const &)) + &std::list<BigNum>::push_back, "push_back"); +
std::list conforms to the requirements
+ of an STL container, we may create a cursor for it:
+
++ + This enables the following use of+// define cursor for an STL conforming container +my_module.def_cursor_for(bignum_list_class); +
BigNumList within Python:
+
++ + The cursor defines random access functions ("__getitem__" and + "__setitem__") for any iterator, but these functions will only be + as efficient as the underlying iterator allows. Indices are in the + range+>>> l = BigNumList() +>>> +>>> l.push_back(BigNum(1)) # fill the list +>>> l.push_back(BigNum(2)) +>>> l.push_back(BigNum(3)) +>>> +>>> for i in l.cursor(): # use list's cursor in a loop +... print i +... +1 +2 +3 +
[0, cursor.len()-1]. You can always
+ access items in any order:
+
++ + but this may be slow (linear time per access) on a large list + which provides only a forward or bi-directional iterator. Note that this + is not a problem for the loop above because it always accesses items + in forward order. + ++>>> cursor = l.cursor() # get cursor +>>> cursor.len() # length of the sequence +3 +>>> print cursor[2] # read element at index +3 +>>> print cursor[0] +1 +>>> cursor[1] = BigNum(42) # write element at index +>>> print cursor[1] +42 +
+ An alternative way of wrapping your containers is to support
+ Python's standard
+ sequence and mapping protocols. The special functions
+ required by these protocols have to be wrapped manually because there
+ are no corresponding
C++ operators that could be used for automatic wrapping. The Python
documentation lists the relevant
diff --git a/src/gen_extclass.py b/src/gen_extclass.py
index f8906970..b7fef7f8 100644
--- a/src/gen_extclass.py
+++ b/src/gen_extclass.py
@@ -324,6 +324,98 @@ class read_only_setattr_function : public function
string m_name;
};
+
+/* helper class to wrap STL conforming iterators.
+
+Given a wrapped container ("FooList", say), this template is used to create
+an auxiliary class "FooList_cursor" that wraps the container's iterator.
+The cursor can be used in Python loops likes this:
+
+ >>> for i in foo_list.cursor():
+ ... print i.get_data()
+
+The auxiliary cursor class can be created for any STL conforming
+container. It implements random access functions (get_item() and
+set_item()) for any iterator, but these will only be as efficient as the
+underlying iterator allows. However, this is not a problem because
+the above Python loop accesses the items in forward order anyway.
+*/
+template
namespace bpl_test {
@@ -1009,6 +1010,15 @@ void init_module(boost::python::module_builder& m)
// export non-operator function as heterogeneous reverse-argument operator
int_class.def(&rmul, "__rmul__");
+ // wrap an STL conforming container
+ boost::python::class_builder