6

Quindi, ho una semplice libreria di eventi, scritta in C++ e usando le librerie Boost. Volevo esporre la suddetta libreria a Python, così naturalmente mi sono rivolto a Boost :: Python. Ho ottenuto il codice per la compilazione, alla fine, ma ora mi trovo di fronte a un bel problema: la mia libreria utilizza tecniche di programmazione di ordine superiore. Ad esempio, la libreria è composta da tre classi principali: una classe evento, una classe gestore eventi e una classe listener di eventi. La classe del listener di eventi pone un problema. Codice:Programmazione di ordine superiore con 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; 

Come si può vedere, la funzione setResponse è il problema. Richiede che venga passata una funzione e, sfortunatamente, Boost :: Python non applica la sua magia del convertitore in questa situazione. Quando viene chiamato come il seguente:

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

dà questo errore:

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

Quindi, la mia domanda è, come potrei risolvere questo problema? Dovrebbe utilizzare l'overloading o un wrapper, come vorrei che la libreria rimanga richiamabile dal C++.

+0

+1 perché penso che Boost :: Python sia un'idea molto interessante. – zmbq

risposta

2

Avrete bisogno di un wrapper intorno a setResponse, che prende uno boost::python::object invece di una funzione. Dovrebbe memorizzare questo bp::object in una posizione nota (probabilmente una variabile membro di una sottoclasse listener).

Quindi passare una funzione C++ diversa alla base setResponse, che saprà come cercare e chiamare la funzione nello bp::object. Se gli eventi devono essere chiamati su un thread diverso, dovrai anche assicurarti di gestire correttamente il Global Interpreter Lock di python, come discusso qui: boost.python not supporting parallelism?.

+1

Grazie! L'ho risolto prima di leggerlo, usando più o meno la stessa metodologia. Ho appena aggiunto un argomento template aggiuntivo al listener, passato in python :: object invece di boost :: function, e lo ho chiamato python_listener con typedef. Funziona come un fascino. – chameco

Problemi correlati