1

What is the correct cythonic way to wrap the following member functions of a boost::geometry::Point? The code snippet comes from here.

    /// @brief Get a coordinate
    /// @tparam K coordinate to get
    /// @return the coordinate
    template <std::size_t K>
    inline CoordinateType const& get() const
    {
#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
        BOOST_GEOMETRY_ASSERT(m_created == 1);
        BOOST_GEOMETRY_ASSERT(m_values_initialized[K] == 1);
#endif
        BOOST_STATIC_ASSERT(K < DimensionCount);
        return m_values[K];
    }

    /// @brief Set a coordinate
    /// @tparam K coordinate to set
    /// @param value value to set
    template <std::size_t K>
    inline void set(CoordinateType const& value)
    {
#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
        BOOST_GEOMETRY_ASSERT(m_created == 1);
        m_values_initialized[K] = 1;
#endif
        BOOST_STATIC_ASSERT(K < DimensionCount);
        m_values[K] = value;
    }

I first attempted using:

cdef extern from "s57/data/geometries.h" namespace "bg::model":
    cdef cppclass _Geo2 "bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree>>":
        _Geo2()
        _Geo2( const _Geo2& other )
        const double get[size_t]() except +
        void set[size_t](double) except +

but then I don't know where to go since something like this:

property x:
    def __set__(self, double value):
        deref(self._p).set[0](value)

gives me this failure:

Error compiling Cython file:
------------------------------------------------------------
...
    property x:
        def __set__(self, double value):
            deref(self._p).set[0](value)
                              ^
------------------------------------------------------------

c:\XXXX\x.pyx:24:31: not parsable as a type

My current working solution has been to create some helper functions like:

double get_geo2_x( geo2& pnt );
double get_geo2_y( geo2& pnt );
void set_geo2_x( geo2& pnt, double value );
void set_geo2_y( geo2& pnt, double value );

Does somebody have in mind a more elegant solution?

gmas80
  • 1,218
  • 1
  • 14
  • 44

1 Answers1

3

You're running into problems with Cython's handling of non-type template parameters. You can manually specify function names using strings, which are inserted directly into the generated C code (see http://docs.cython.org/src/userguide/external_C_code.html#resolving-naming-conflicts-c-name-specifications)

As a very simple example

// example.hpp
#include <iostream> 

class C {
  template <int K>
  void set(double value) {
      std::cout << K << ": " << value << std::endl;
  }

And the Cython code

cdef extern from "example.hpp":
    cdef cppclass C:
        void set0 "set<0>"(double) except +
        void set1 "set<1>"(double) except + 


def do_set():
    # very simple illustrative example
    cdef C c
    c.set0(1.0)
    c.set1(1.5)
}

Whenever Cython sees set0 called on a C it substitutes set<0>, calling the template function directly. You can then use properties, as you were trying to do.

This probably isn't significantly better than creating helper functions, but it might be a little easier.

DavidW
  • 29,336
  • 6
  • 55
  • 86