Ошибка компиляции Cython с простым наследованием - объект не имеет атрибута - PullRequest
0 голосов
/ 30 апреля 2019

Я пытаюсь обернуть простой класс C ++, который использует общие указатели и очень простое наследование.У меня есть класс Point, который является базовым классом, а SphericalPoint - это дочерний класс.У меня есть вектор общих указателей очков.Я хочу, чтобы вектор содержал в себе дочерние объекты класса, т.е. сферические точки.Может быть много дочерних классов Point, и сферическая точка показана здесь только для представления.Когда я делаю это, я получаю следующую ошибку компиляции -

 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'

Первоначально при поиске в Google я подумал, что причиной проблемы может быть, потому что у меня нет ключевого слова public в Cythonкод, но когда я добавляю ключевое слово public, я получаю массу других ошибок.В следующей ссылке Wrapping C ++ с Cython нет примера, который бы отображал public в файле .pxd.

Вот MVCE, который воспроизводит проблему.Как я могу исправить эту ошибку?Версия Cython - 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);
    };

, и это мой файл point.pxd

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)

И мой файл point.pyx

 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)

ОБНОВЛЕНИЕ

Я только что переместил создание дочерних классов в отдельный метод, потому что он на самом деле не является частью cinit .Но я все равно получаю те же ошибки компиляции.Мне также интересно, является ли причиной проблемы создание экземпляра подкласса SphericalPoint, т.е.

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

Это рекомендуемый способ?

1 Ответ

1 голос
/ 01 мая 2019

Cython может решить эту проблему для обычных типов указателей и сгенерировать код C ++ с помощью ->, однако он не может решить эту проблему для типов, которые реализуют интерфейс указателей с перегрузкой операторов.

Вместо этого выследует использовать cython.operator.dereference.

from cython.operator cimport dereference

# ...

dereference(point).setCoordinate1(instance)
...