6

Tengo una biblioteca de eventos simple, escrita en C++ y que usa las bibliotecas de Boost. Quería exponer dicha biblioteca a Python, así que naturalmente recurrí a Boost :: Python. Obtuve el código para compilar, eventualmente, pero ahora me enfrento con bastante problema: mi biblioteca utiliza técnicas de programación de orden superior. Por ejemplo, la biblioteca se compone de tres clases principales: una clase de evento, una clase de administrador de eventos y una clase de detector de eventos. La clase de escucha de eventos plantea un problema. Código:Programación de orden superior 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; 

Como se puede ver, la función setResponse es el problema. Requiere que se le pase una función y, desafortunadamente, Boost :: Python no aplica su magia de convertidor en esta situación. Cuando se llama como la siguiente:

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

se da este error:

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

lo tanto, mi pregunta es, ¿cómo puedo solucionar esto? Tendría que usar sobrecarga o un contenedor, ya que me gustaría que la biblioteca siga siendo invocable por C++.

+0

+1 porque creo que Boost :: Python es una idea genial. – zmbq

Respuesta

2

Necesitará un contenedor alrededor de setResponse, que toma un boost::python::object en lugar de una función. Debe almacenar este bp::object en una ubicación conocida (probablemente una variable miembro de una subclase listener).

Luego pase una función de C++ diferente a la base setResponse, que sabrá cómo buscar y llamar a la función en el bp::object. Si se van a invocar sucesos en un hilo diferente, también deberá garantizar el manejo adecuado del bloqueo de intérprete global de python, como se explica aquí: boost.python not supporting parallelism?.

+1

¡Gracias! Lo arreglé antes de leer esto, usando casi la misma metodología. Acabo de agregar un argumento de plantilla adicional al oyente, pasado en python :: object en lugar de boost :: function, y lo llamé python_listener con un typedef. Funciona de maravilla. – chameco

Cuestiones relacionadas