관찰자 패턴은 Cython 바인딩을 통해 Python 인터프리터에 노출하려는 내 C++ 프로젝트에 자주 나타납니다. 상황을 보여주는 최소한의 예를 만들려고했습니다. 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
파일의 내용이다 : event()
인 경우
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?
이 컴파일 않지만, 세그먼테이션 폴트 (segfault)를 옵서버에게 알립니다 :
>>> spec = CythonMinimal.Spectacle()
>>> look = CythonMinimal.Onlooker()
>>> spec.registerObserver(look)
>>> spec.event()
event triggered
Segmentation fault: 11
여기서의 문제점은 무엇이며 어떻게 수정 될 수 있습니까?
스펙터클과 비슷한 방법으로 cdef 클래스 옵서버를 만든 다음 def registerObserver (self, Observer observer) : self._this.registerObserver (& observer._this)'입니다. –
@CzarekTomczak 예제를 확장하고 조언을 통합했지만 여전히 문제가 있습니다. 'observer._this'는'_Observer'의 인스턴스가 될 수 없습니다. 왜냐하면'_Observer'는 abstract (순수 가상 메소드를가집니다)이기 때문입니다. 나는 그것을 컴파일하기 위해'_Observer *'로 변경했다. – clstaudt