6

Mam więc prostą bibliotekę zdarzeń napisaną w języku C++ i bibliotekę Boost. Chciałem udostępnić tę bibliotekę Pythonowi, więc naturalnie zwróciłem się do Boost :: Python. W końcu udało mi się skompilować kod, ale teraz mam już dość problemu: moja biblioteka wykorzystuje techniki programowania wyższego rzędu. Na przykład biblioteka składa się z trzech głównych klas: klasa zdarzenia, klasa menedżera zdarzeń i klasa nasłuchiwania zdarzeń. Klasa detektora zdarzeń stanowi problem. Kod:Programowanie wyższego rzędu za pomocą 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; 

Jak widać, problemem jest funkcja setResponse. Wymaga podania funkcji, a niestety Boost :: Python nie stosuje tej magii konwertera w tej sytuacji. Wywołany tak:

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

daje ten błąd:

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)>) 

Więc moje pytanie brzmi: w jaki sposób mogę rozwiązać ten problem? Musiałby albo użyć przeciążenia, albo wrappera, ponieważ chciałbym, aby biblioteka pozostała wywoływana przez C++.

+0

+1 ponieważ myślę, że Boost :: Python to bardzo fajny pomysł. – zmbq

Odpowiedz

2

Będziesz potrzebować opakowania o numerze setResponse, które zamiast funkcji ma funkcję boost::python::object. Powinien przechowywać to bp::object w znanym miejscu (prawdopodobnie zmienna składowa podklasy listener).

Następnie należy przekazać inną funkcję C++ do bazy setResponse, która będzie znała sposób wyszukiwania i wywoływania funkcji w bp::object. Jeśli zdarzenia mają być wywoływane w innym wątku, będziesz również musiał zapewnić poprawną obsługę globalnej blokady interpretera Pythona, tak jak to omówiono tutaj: boost.python not supporting parallelism?.

+1

Dzięki! Naprawiłem to, zanim to przeczytam, używając prawie tej samej metodologii. Właśnie dodałem dodatkowy argument szablonu do detektora, przekazany w python :: object zamiast boost :: function, i nazwał go python_listener z typedef. Działa jak marzenie. – chameco

Powiązane problemy