Шаблон наблюдателя часто появляется в моем проекте на C++, который я теперь хочу представить интерпретатору Python с помощью привязок Cython. Я попытался построить минимальный пример, иллюстрирующий ситуацию. A Spectacle
принимает любой объект, полученный из абстрактного базового класса Observer
, такого как Onlooker
. Когда мы вызываем Spectacle::event()
, каждый зарегистрированный наблюдатель уведомляется.Обертка шаблона наблюдателя с Cython
Это содержимое файла ObserverPattern.h
:
class Spectacle {
private:
std::vector<Observer*> observers;
public:
Spectacle() {};
virtual ~Spectacle() {};
virtual void registerObserver(Observer* observer) {
this->observers.push_back(observer);
}
virtual void event() {
std::cout << "event triggered" << std::endl;
for (Observer* observer : this->observers) {
observer->onEvent();
}
}
};
class Observer {
public:
Observer() {};
virtual ~Observer() {};
virtual void onEvent() = 0;
};
class Onlooker : public Observer {
public:
Onlooker() {};
virtual ~Onlooker() {};
virtual void onEvent() {
std::cout << "event observed" << std::endl;
}
};
И это содержание моего .pyx
файла, содержащий привязок:
cdef extern from "ObserverPattern.h":
cdef cppclass _Spectacle "Spectacle":
_Spectacle() except +
void registerObserver(_Observer* observer)
void event()
cdef extern from "ObserverPattern.h":
cdef cppclass _Observer "Observer":
_Observer() except +
void onEvent()
cdef extern from "ObserverPattern.h":
cdef cppclass _Onlooker "Onlooker":
_Onlooker() except +
void onEvent()
cdef class Spectacle:
cdef _Spectacle _this
def event(self):
self._this.event()
def registerObserver(self, Observer observer):
self._this.registerObserver(observer._this)
cdef class Observer:
cdef _Observer* _this # must be a pointer because _Observer has pure virtual method
cdef class Onlooker(Observer):
pass # what should be the class body?
Это компилируется, но ошибки сегментации при event()
является и уведомления наблюдателей:
>>> spec = CythonMinimal.Spectacle()
>>> look = CythonMinimal.Onlooker()
>>> spec.registerObserver(look)
>>> spec.event()
event triggered
Segmentation fault: 11
В чем проблема и как может выглядеть проблема?
Создайте класс наблюдателя cdef так же, как вы сделали с Spectacle, а затем «def registerObserver (self, Observer observer): self._this.registerObserver (& observer._this) '. –
@CzarekTomczak Я расширил этот пример и включил ваш совет, но все еще есть проблема. Обратите внимание: 'observer._this' не может быть экземпляром' _Observer', потому что '_Observer' является абстрактным (имеет чистый виртуальный метод). Я изменил его на '_Observer *', чтобы он скомпилировался. – clstaudt