pythonc++boostcppyy

Calling boost rtree from python


I am trying to adapt this boost rtree example so that python calls the c++ libraries. This is my first attempt at calling c++ from python. I am using cppyy 1.8.5 (python version 3.6.7) and boost rtree header-only library (boost version 1.58) on ubuntu 16.04.7 LTS. Here is the code that I have so far.

import cppyy
cppyy.set_debug()
import cppyy.ll
cppyy.ll.set_signals_as_exception(True)

cppyy.add_include_path('/usr/include')
cppyy.include('boost/geometry.hpp')
cppyy.include('boost/geometry/geometries/point.hpp')
cppyy.include('boost/geometry/geometries/box.hpp')
cppyy.include('boost/geometry/index/rtree.hpp')
cppyy.include('vector')
cppyy.include('iostream')
cppyy.include('boost/foreach.hpp')

cpp = cppyy.gbl
std = cpp.std
bg = cpp.boost.geometry
bgi = cpp.boost.geometry.index

point = bg.model.point[float, 2, bg.cs.cartesian]
box = bg.model.box[point]
value = std.pair[box, 'unsigned']
rtree = bgi.rtree[value, bgi.quadratic(16)]

for i in range(10):
    b = box(point(i + 0.0, i + 0.0), point(i + 0.5, i + 0.5))
    print(bg.wkt[box](b))
    with cppyy.ll.signals_as_exception():
        rtree.insert(std.make_pair(b, i))

In the for loop, the box is created but the rtree.insert() call produces an error.

$ python try_cppyy_rtree.py
TClass::GetClass: Header Parsing - The representation of __cppyy_internal was not found in the type system. A lookup in the interpreter is about to be tried: this can cause parsing. This can be avoided selecting __cppyy_internal in the linkdef/selection file.
...<trimmed>...
TClass::GetClass: Header Parsing - The representation of boost::geometry::wkt_manipulator<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> > > was not found in the type system. A lookup in the interpreter is about to be tried: this can cause parsing. This can be avoided selecting boost::geometry::wkt_manipulator<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> > > in the linkdef/selection file.
POLYGON((0 0,0 0.5,0.5 0.5,0.5 0,0 0))
TClass::GetClass: Header Parsing - The representation of std::make_pair was not found in the type system. A lookup in the interpreter is about to be tried: this can cause parsing. This can be avoided selecting std::make_pair in the linkdef/selection file.
TClass::GetClass: Header Parsing - The representation of std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,int> was not found in the type system. A lookup in the interpreter is about to be tried: this can cause parsing. This can be avoided selecting std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,int> in the linkdef/selection file.
TClass::GetClass: Header Parsing - The representation of std::__pair_base<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,int> was not found in the type system. A lookup in the interpreter is about to be tried: this can cause parsing. This can be avoided selecting std::__pair_base<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,int> in the linkdef/selection file.
In file included from input_line_19:1:
In file included from /usr/include/boost/geometry.hpp:17:
In file included from /usr/include/boost/geometry/geometry.hpp:43:
In file included from /usr/include/boost/geometry/core/radian_access.hpp:28:
In file included from /usr/include/boost/geometry/util/math.hpp:28:
In file included from /usr/include/boost/math/constants/constants.hpp:18:
In file included from /usr/include/boost/lexical_cast.hpp:30:
In file included from /usr/include/boost/range/iterator_range_core.hpp:38:
In file included from /usr/include/boost/range/functions.hpp:18:
/usr/include/boost/range/begin.hpp:47:17: error: member reference type 'std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, int> *const' is a pointer; did you mean
  to use '->'?
        return c.begin();
               ~^
                ->
/usr/include/boost/range/begin.hpp:111:12: note: in instantiation of function template specialization 'boost::range_detail::range_begin<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2,
  boost::geometry::cs::cartesian> >, int> *const>' requested here
    return range_begin( r );
           ^
/usr/include/boost/range/begin.hpp:127:46: note: in instantiation of function template specialization 'boost::range_adl_barrier::begin<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2,
  boost::geometry::cs::cartesian> >, int> *>' requested here
            return boost::range_adl_barrier::begin( r );
                                             ^
/usr/include/boost/geometry/index/rtree.hpp:1417:30: note: in instantiation of function template specialization 'boost::range_adl_barrier::const_begin<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2,
  boost::geometry::cs::cartesian> >, int> *>' requested here
        for ( It it = boost::const_begin(rng); it != boost::const_end(rng) ; ++it )
                             ^
/usr/include/boost/geometry/index/rtree.hpp:624:15: note: in instantiation of function template specialization 'boost::geometry::index::rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2,
  boost::geometry::cs::cartesian> >, unsigned int>, boost::geometry::index::quadratic<16, 4>,
  boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, unsigned int> >,
  boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, unsigned int> >,
  std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, unsigned int> >
  >::insert_dispatch<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, int> *>' requested here
        this->insert_dispatch(conv_or_rng, is_conv_t());
              ^
note: in instantiation of function template specialization 'boost::geometry::index::rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2,
  boost::geometry::cs::cartesian> >, unsigned int>, boost::geometry::index::quadratic<16, 4>,
  boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, unsigned int> >,
  boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, unsigned int> >,
  std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, unsigned int> >
  >::insert<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, int> *>' requested here
In file included from input_line_19:1:
In file included from /usr/include/boost/geometry.hpp:17:
In file included from /usr/include/boost/geometry/geometry.hpp:43:
In file included from /usr/include/boost/geometry/core/radian_access.hpp:28:
In file included from /usr/include/boost/geometry/util/math.hpp:28:
In file included from /usr/include/boost/math/constants/constants.hpp:18:
In file included from /usr/include/boost/lexical_cast.hpp:30:
In file included from /usr/include/boost/range/iterator_range_core.hpp:38:
In file included from /usr/include/boost/range/functions.hpp:18:
/usr/include/boost/range/begin.hpp:47:18: error: no member named 'begin' in 'std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, int>'
        return c.begin();
               ~ ^
In file included from input_line_19:1:
In file included from /usr/include/boost/geometry.hpp:17:
In file included from /usr/include/boost/geometry/geometry.hpp:43:
In file included from /usr/include/boost/geometry/core/radian_access.hpp:28:
In file included from /usr/include/boost/geometry/util/math.hpp:28:
In file included from /usr/include/boost/math/constants/constants.hpp:18:
In file included from /usr/include/boost/lexical_cast.hpp:30:
In file included from /usr/include/boost/range/iterator_range_core.hpp:38:
In file included from /usr/include/boost/range/functions.hpp:19:
/usr/include/boost/range/end.hpp:48:21: error: member reference type 'std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, int> *const' is a pointer; did you mean
  to use '->'?
            return c.end();
                   ~^
                    ->
/usr/include/boost/range/end.hpp:105:12: note: in instantiation of function template specialization 'boost::range_detail::range_end<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2,
  boost::geometry::cs::cartesian> >, int> *const>' requested here
    return range_end( r );
           ^
/usr/include/boost/range/end.hpp:121:46: note: in instantiation of function template specialization 'boost::range_adl_barrier::end<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2,
  boost::geometry::cs::cartesian> >, int> *>' requested here
            return boost::range_adl_barrier::end( r );
                                             ^
/usr/include/boost/geometry/index/rtree.hpp:1417:61: note: in instantiation of function template specialization 'boost::range_adl_barrier::const_end<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2,
  boost::geometry::cs::cartesian> >, int> *>' requested here
        for ( It it = boost::const_begin(rng); it != boost::const_end(rng) ; ++it )
                                                            ^
/usr/include/boost/geometry/index/rtree.hpp:624:15: note: in instantiation of function template specialization 'boost::geometry::index::rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2,
  boost::geometry::cs::cartesian> >, unsigned int>, boost::geometry::index::quadratic<16, 4>,
  boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, unsigned int> >,
  boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, unsigned int> >,
  std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, unsigned int> >
  >::insert_dispatch<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, int> *>' requested here
        this->insert_dispatch(conv_or_rng, is_conv_t());
              ^
note: in instantiation of function template specialization 'boost::geometry::index::rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2,
  boost::geometry::cs::cartesian> >, unsigned int>, boost::geometry::index::quadratic<16, 4>,
  boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, unsigned int> >,
  boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, unsigned int> >,
  std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, unsigned int> >
  >::insert<std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, int> *>' requested here
In file included from input_line_19:1:
In file included from /usr/include/boost/geometry.hpp:17:
In file included from /usr/include/boost/geometry/geometry.hpp:43:
In file included from /usr/include/boost/geometry/core/radian_access.hpp:28:
In file included from /usr/include/boost/geometry/util/math.hpp:28:
In file included from /usr/include/boost/math/constants/constants.hpp:18:
In file included from /usr/include/boost/lexical_cast.hpp:30:
In file included from /usr/include/boost/range/iterator_range_core.hpp:38:
In file included from /usr/include/boost/range/functions.hpp:19:
/usr/include/boost/range/end.hpp:48:22: error: no member named 'end' in 'std::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> >, int>'
            return c.end();
                   ~ ^
Traceback (most recent call last):
  File "try_cppyy_rtree.py", line 58, in <module>
    rtree.insert(std.make_pair(b, i))
TypeError: Template method resolution failed:
  void boost::geometry::index::rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int>,boost::geometry::index::quadratic<16,4>,boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> > >::insert(const boost::geometry::index::rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int>,boost::geometry::index::quadratic<16,4>,boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> > >::value_type& value) =>
TypeError: unbound method rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int>,boost::geometry::index::quadratic<16,4>,boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> > >::insert must be called with a rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int>,boost::geometry::index::quadratic<16,4>,boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> > > instance as first argument
  void boost::geometry::index::rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int>,boost::geometry::index::quadratic<16,4>,boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> > >::insert(const std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,int>& conv_or_rng) =>
TypeError: unbound method rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int>,boost::geometry::index::quadratic<16,4>,boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> > >::insert must be called with a rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int>,boost::geometry::index::quadratic<16,4>,boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> > > instance as first argument
  void boost::geometry::index::rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int>,boost::geometry::index::quadratic<16,4>,boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> > >::insert(std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,int>*const& conv_or_rng) =>
TypeError: unbound method rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int>,boost::geometry::index::quadratic<16,4>,boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> > >::insert must be called with a rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int>,boost::geometry::index::quadratic<16,4>,boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> > > instance as first argument
  void boost::geometry::index::rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int>,boost::geometry::index::quadratic<16,4>,boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> > >::insert(const std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,int>& conv_or_rng) =>
TypeError: unbound method rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int>,boost::geometry::index::quadratic<16,4>,boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> > >::insert must be called with a rtree<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int>,boost::geometry::index::quadratic<16,4>,boost::geometry::index::indexable<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,boost::geometry::index::equal_to<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> >,std::allocator<std::pair<boost::geometry::model::box<boost::geometry::model::point<float,2,boost::geometry::cs::cartesian> >,unsigned int> > > instance as first argument

Any insights on how to get this working? Is using cppyy recommended for what I am attempting? I chose cppyy initially because examples I see using other methods seem to require an object file, but boost rtree is a header-only library.


Solution

  • Any reason for using cppyy 1.8.5? The problem with the script is independent of cppyy version, but I've only verified that it runs correctly with 2.0.0 (which is based on a newer version of Clang).

    The problem is with this line:

    rtree = bgi.rtree[value, bgi.quadratic(16)]
    

    makes that rtree is still only a type object. Compare the syntax to the preceding typedefs that you (correctly) transliterated before that. To get an actual instance of the bgi::rtree, you need to instantiate the type:

    rtree = bgi.rtree[value, bgi.quadratic(16)]()
    

    Note the extra ().

    I checked and b is copied, so creating the boxes in a loop should be fine. Otherwise, with Python, since b will be garbage collected (same as in C++ in the original example, really, as there they are stack objects), its lifetime should have been managed (e.g. by using smart pointers).