6

그래서 C++로 작성되고 Boost 라이브러리를 사용하는 간단한 이벤트 라이브러리가 있습니다. 나는이 라이브러리를 파이썬에 공개하고 싶었 기 때문에 자연스럽게 Boost :: Python으로 변했다. 결국 컴파일 할 코드가 생겼지 만 이제는 문제가 생겼습니다. 라이브러리는 고차 프로그래밍 기술을 사용합니다. 예를 들어, 라이브러리는 이벤트 클래스, 이벤트 관리자 클래스 및 이벤트 리스너 클래스의 세 가지 기본 클래스로 구성됩니다. 이벤트 리스너 클래스에 문제가 발생합니다. 코드 :Boost :: Python을 사용한 고차 프로그래밍

class listener{ 
     public: 
      listener(){} 
      void alert(cham::event::event e){ 
       if (responses[e.getName()]) 
        responses[e.getName()](e.getData()); 
      } 
      void setResponse(std::string n, boost::function<void (std::string d)> c){responses.insert(make_pair(n, c));} 
      void setManager(_manager<listener> *m){manager = m;} 
     private: 
      std::map<std::string, boost::function<void (std::string d)> > responses; 
      _manager<listener> *manager; 

여기서 알 수 있듯이 setResponse 함수가 문제입니다. 불행하게도 Boost :: Python은이 상황에서 변환기 마법을 적용하지 않습니다. 다음과 같은 전화했을 때 :

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
Boost.Python.ArgumentError: Python argument types in 
    listener.setResponse(listener, str, function) 
did not match C++ signature: 
    setResponse(cham::event::listener {lvalue}, std::string, boost::function<void()(std::string)>) 

그래서, 내 질문은, 어떻게이 문제를 해결 수 :

>>> import chameleon 
>>> man = chameleon.manager() 
>>> lis = chameleon.listener() 
>>> def oup(s): 
... print s 
... 
>>> lis.setResponse("event", oup) 

는이 오류를 준다? 라이브러리를 C++에서 호출 가능하도록 유지하려면 오버로드 또는 래퍼를 사용해야합니다.

+0

+1 왜냐하면 Boost :: Python은 매우 멋진 아이디어라고 생각하기 때문입니다. – zmbq

답변

2

setResponse 래퍼가 필요하며 기능 대신 boost::python::object이 필요합니다. 알려진 위치에 bp::object을 저장해야합니다 (아마도 listener 하위 클래스의 멤버 변수 일 수 있습니다).

setResponse에 다른 C++ 함수를 전달하면 bp::object에서 함수를 검색하고 호출하는 방법을 알 수 있습니다. 이벤트가 다른 스레드에서 호출되는 경우 여기에서 설명한대로 파이썬의 전역 인터프리터 잠금을 올바르게 처리해야합니다. boost.python not supporting parallelism?.

+1

감사! 거의 동일한 방법론을 사용하여 이것을 읽지 전에 수정했습니다. 방금 템플릿 인수를 listener에 추가하여 boost :: function 대신 python :: object에 전달하고 typedef로 python_listener라는 이름을 지정했습니다. 매력처럼 작동합니다. – chameco