Search code examples
pythonc++cgalpybind11

cgal c++ integration in python3.6 template error


I try to integrate cgal library to my python program. I made some test by following diverse tutorial. And I try to do a template but I have an error when I compile and I don't know how to fixe it. I use pybind11 to integrate cgal.

Part of my mesher.cpp code :

template <typename T>
class TypedInputIterator
{
public:
    typedef T value_type;
    typedef T& reference;
    typedef T* pointer;

    explicit TypedInputIterator(py::iterator& py_iter):
            py_iter_(py_iter){}

    explicit TypedInputIterator(py::iterator&& py_iter):
            py_iter_(py_iter){}

    value_type operator*(){
        return (*py_iter_).template cast<value_type>();
    }

    TypedInputIterator operator++(int){
        auto copy = *this;
        ++py_iter_;
        return copy;
    }

    TypedInputIterator& operator++(){
        ++py_iter_;
        return *this;
    }

    bool operator != (TypedInputIterator &rhs) {
        return py_iter_ != rhs.py_iter_;
    }

    bool operator == (TypedInputIterator &rhs) {
        return py_iter_ == rhs.py_iter_;
    }

private:
    py::iterator py_iter_;
};

PYBIND11_MODULE(cgal_mesher, m)
{

    py::class_<Point>(m, "Point")
                    .def(py::init<int,int>(), py::arg("x"), py::arg("y"))
                    .def(py::init<double,double>(), py::arg("x"), py::arg("y"))
                    .def_property_readonly("x", &Point::x)
                    .def_property_readonly("y", &Point::y)
                    .def("__repr__",
                         [](const Point &p){
                            std::string r("Point(");
                            r += boost::lexical_cast<std::string>(p.x());
                            r += ", ";
                            r += boost::lexical_cast<std::string>(p.y());
                            r +=")";
                            return r;
                         })
                    .def("__hash__",
                         [](const Point &p){
                            std::hash<double> double_hash;
                            auto x_hash = double_hash(p.x());
                            auto y_hash = double_hash(p.y());
                            return y_hash ^ x_hash + 0x9e1779b9 + (y_hash << 6) + (y_hash >> 2);
                         })
                    .def("__eq__",
                         [](const Point &p, const Point & q) {
                            return p == q;
                         })
                    ;

    py::class_<Mesher>(m, "Mesher")
                    .def(py::init<CDT&>())
                    .def("seeds_from", [](Mesher & mesher, py::iterable iterable)
                    {
                        py::iterator iterator = py::iter(iterable);
                        TypedInputIterator<Point> points_begin(iterator);
                        TypedInputIterator<Point> points_end(py::iterator::sentinel());
                        mesher.set_seeds(points_begin, points_end);
                    })

                    ;
}

I know that the error append to this line :

mesher.set_seeds(points_begin, points_end);

because when I comment it, there is no error message anymore.

The error message :

[ 50%] Building CXX object CMakeFiles/cgal_mesher.dir/src/mesher/cgal_mesher.cpp.o /usr/bin/c++  
-DCGAL_USE_CORE=1 -DCGAL_USE_GMP -DCGAL_USE_MPFR -Dcgal_mesher_EXPORTS -isystem /home/admin-suz/anaconda3/include -I/home/admin-suz/Documents/Code/Interface_CGAL_python/mesher/build/temp.linux-x86_64-3.6
-isystem /usr/local/include -I/home/admin-suz/Documents/Code/Interface_CGAL_python/mesher/src/mesher
-I/home/admin-suz/Documents/Code/Interface_CGAL_python/mesher/lib/pybind11/include
-I/home/admin-suz/anaconda3/include/python3.6m  -DVERSION_INFO=\"0.1\"  -O3 -DNDEBUG -fPIC -fvisibility=hidden   -std=c++14 -flto -fno-fat-lto-objects -frounding-math -o CMakeFiles/cgal_mesher.dir/src/mesher/cgal_mesher.cpp.o -c /home/admin-suz/Documents/Code/Interface_CGAL_python/mesher/src/mesher/cgal_mesher.cpp In file included from /usr/include/c++/5/bits/forward_list.h:38:0,
                 from /usr/include/c++/5/forward_list:38,
                 from /home/admin-suz/Documents/Code/Interface_CGAL_python/mesher/lib/pybind11/include/pybind11/detail/common.h:140,
                 from /home/admin-suz/Documents/Code/Interface_CGAL_python/mesher/lib/pybind11/include/pybind11/pytypes.h:12,
                 from /home/admin-suz/Documents/Code/Interface_CGAL_python/mesher/lib/pybind11/include/pybind11/cast.h:13,
                 from /home/admin-suz/Documents/Code/Interface_CGAL_python/mesher/lib/pybind11/include/pybind11/attr.h:13,
                 from /home/admin-suz/Documents/Code/Interface_CGAL_python/mesher/lib/pybind11/include/pybind11/pybind11.h:43,
                 from /home/admin-suz/Documents/Code/Interface_CGAL_python/mesher/src/mesher/cgal_mesher.cpp:1: /usr/include/c++/5/bits/stl_algobase.h: In instantiation of ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = TypedInputIterator<CGAL::Point_2<CGAL::Epick> >; _OI = std::back_insert_iterator<std::__cxx11::list<CGAL::Point_2<CGAL::Epick>, std::allocator<CGAL::Point_2<CGAL::Epick> > > >]’: /usr/include/c++/5/bits/stl_algobase.h:438:45:   required from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = TypedInputIterator<CGAL::Point_2<CGAL::Epick> >; _OI = std::back_insert_iterator<std::__cxx11::list<CGAL::Point_2<CGAL::Epick>, std::allocator<CGAL::Point_2<CGAL::Epick> > > >]’ /usr/include/c++/5/bits/stl_algobase.h:471:8:   required from ‘_OI std::copy(_II, _II, _OI) [with _II = TypedInputIterator<CGAL::Point_2<CGAL::Epick> >; _OI = std::back_insert_iterator<std::__cxx11::list<CGAL::Point_2<CGAL::Epick>, std::allocator<CGAL::Point_2<CGAL::Epick> > > >]’ /usr/local/include/CGAL/Delaunay_mesher_2.h:137:14:   required from ‘void CGAL::Delaunay_mesher_2<Tr, Crit>::set_seeds(InputIterator, InputIterator, bool, bool) [with InputIterator = TypedInputIterator<CGAL::Point_2<CGAL::Epick> >; Tr = CGAL::Constrained_Delaunay_triangulation_2<CGAL::Epick, CGAL::Triangulation_data_structure_2<CGAL::Delaunay_mesh_vertex_base_2<CGAL::Epick>, CGAL::Delaunay_mesh_face_base_2<CGAL::Epick> > >; Crit = CGAL::Delaunay_mesh_size_criteria_2<CGAL::Constrained_Delaunay_triangulation_2<CGAL::Epick, CGAL::Triangulation_data_structure_2<CGAL::Delaunay_mesh_vertex_base_2<CGAL::Epick>, CGAL::Delaunay_mesh_face_base_2<CGAL::Epick> > > >]’ /home/admin-suz/Documents/Code/Interface_CGAL_python/mesher/src/mesher/cgal_mesher.cpp:169:66: required from here /usr/include/c++/5/bits/stl_algobase.h:393:57: error: no type named ‘value_type’ in ‘struct std::iterator_traits<TypedInputIterator<CGAL::Point_2<CGAL::Epick> >
>’
       typedef typename iterator_traits<_II>::value_type _ValueTypeI;
                                                         ^ /usr/include/c++/5/bits/stl_algobase.h:395:64: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<TypedInputIterator<CGAL::Point_2<CGAL::Epick> >
>’
       typedef typename iterator_traits<_II>::iterator_category _Category;
                                                                ^ /usr/include/c++/5/bits/stl_algobase.h:399:9: error: no type named ‘value_type’ in ‘struct std::iterator_traits<TypedInputIterator<CGAL::Point_2<CGAL::Epick> >
>’
         && __are_same<_ValueTypeI, _ValueTypeO>::__value);
         ^ /usr/include/c++/5/bits/stl_algobase.h:402:44: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<TypedInputIterator<CGAL::Point_2<CGAL::Epick> >
>’
                        _Category>::__copy_m(__first, __last, __result);
                                            ^ CMakeFiles/cgal_mesher.dir/build.make:65 : la recette pour la cible « CMakeFiles/cgal_mesher.dir/src/mesher/cgal_mesher.cpp.o » a échouée make[2]: *** [CMakeFiles/cgal_mesher.dir/src/mesher/cgal_mesher.cpp.o] Erreur 1 make[2] : on quitte le répertoire « /home/admin-suz/Documents/Code/Interface_CGAL_python/mesher/build/temp.linux-x86_64-3.6 » CMakeFiles/Makefile2:70 : la recette pour la cible « CMakeFiles/cgal_mesher.dir/all » a échouée make[1]: *** [CMakeFiles/cgal_mesher.dir/all] Erreur 2 make[1] : on quitte le répertoire « /home/admin-suz/Documents/Code/Interface_CGAL_python/mesher/build/temp.linux-x86_64-3.6 » Makefile:97 : la recette pour la cible « all » a échouée

Thank you for your help.

I'm using ubuntu 16.4 and python 3.6.


Solution

  • My original code which you've used, above, was compiled with Clang rather than gcc. If you read this article https://www.fluentcpp.com/2018/05/08/std-iterator-deprecated/ you will see that there are differences in how std::iterator_traits is implemented for Clang. It seems my code provides sufficient type information for the Clang implementation of iterator_traits to work, but not enough for the gcc implementation.

    In particular, the code for TypedInputIterator defines value_type, reference and pointer, but neither iterator_category nor difference_type. Therefore, two two missing typedefs need to be added with the other typedefs near the top of the iterator class:

    typedef std::input_iterator_tag iterator_category;
    typedef std::ptrdiff_t difference_type;
    

    This gives the full set of five. You'll should also include two headers to make these types available:

    #include <iterator>
    #include <cstddef>