0

I am trying to wrap a simple C++ class that uses shared pointers and a very simple inheritance. I have a class Point that is a base class and SphericalPoint is it's child class. I have a vector of shared pointers of Points. I want the vector to hold the child class objects in it i.e. Spherical Points. There can be many child classes of Point and Spherical Point is only shown here for representation. When I do this I get the following compilation error -

 point.pyx:18:13: Object of type 'shared_ptr[Point]' has no attribute 'setCoordinate1'

Error compiling Cython file:

    point = shared_ptr[Point](new SphericalPoint())
    cdef double latitude, longitude
    latitude = 0.
    longitude = 0.
    point.setCoordinate1(latitude)
    point.setCoordinate2(longitude)


  point.pyx:19:13: Object of type 'shared_ptr[Point]' has no attribute 'setCoordinate2'

Initially when googling for this I thought the cause of the problem maybe because I do not have the keyword public in the Cython code but when I do add the keyword public I get a whole bunch of other errors. In the following link Wrapping C++ with Cython there is no example that shows public in the .pxd file.

Here is a MVCE that reproduces the problem. How can I fix this error ? Cython version is 0.29.7

Point.h

class Point {
   private:
     double coordinate1,coordinate2;
   public:
     virtual double  getCoordinate1();
     virtual double  getCoordinate2();
     virtual void    setCoordinate1(double coordinate1);
     virtual void    setCoordinate2(double coordinate2);
   };

class SphericalPoint : public Point
   {
     private:
         double longitude,latitude;
     public:
         double getCoordinate1();
         double getCoordinate2();
         void   setCoordinate1(double latitude);
         void   setCoordinate2(double longitude);
    };

and this is my point.pxd file

cdef extern from "Point.h":
    cdef cppclass Point:
       Point() except +
       double getCoordinate1()
       double getCoordinate2()
       void setCoordinate1(double coordinate1)
       void setCoordinate2(double coordinate2)

   cdef cppclass SphericalPoint(Point):
      SphericalPoint() except +
      double getCoordinate1()
      double getCoordinate2()
      void setCoordinate1(double coordinate1)
      void setCoordinate2(double coordinate2)

And my point.pyx file

 from libcpp.memory cimport shared_ptr
 from libcpp.vector cimport vector

 from point cimport Point

 cdef class PyA:

     cdef vector[shared_ptr[Point]]* points

     def __cinit__(self):
        self.points = new vector[shared_ptr[Point]]()

     def buildPoints(self):

        cdef shared_ptr[Point] point
        point = shared_ptr[Point](new SphericalPoint())
        cdef double latitude, longitude
        point.setCoordinate1(latitude)
        point.setCoordinate2(longitude)

UPDATE

I just moved the instantiation of the child classes to it's own separate method because it is not really part of cinit. But I still get the same compilation errors. I am also wondering whether the instantiation of the subclass SphericalPoint is the cause of the problem i.e.

  point = shared_ptr[Point](new SphericalPoint())

Is this the recommended way ?

1 Answer 1

1

Cython can work this out for regular pointer types and generate c++ code with ->, however it isn't able to work this out for types that implement a pointer interface with operator overloading.

Instead you should use cython.operator.dereference.

from cython.operator cimport dereference

# ...

dereference(point).setCoordinate1(instance)
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you that works !! I had one other question in this context . Is the new operator the recommended way to instantiate new objects in Cython? Generally in C++ (most SO answers recommend this) not to use new. Any comments ?
In Cython you often can't initialise things on the stack because they're default allocated at the start of the function (to get Python scoping rules). In this case new is often the best solution.
Excellent thanks. A privilege to learn from you. Upvoted and accepted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.