Программирование высшего порядка с использованием Boost :: Python - PullRequest
6 голосов
/ 28 февраля 2012

Итак, у меня есть простая библиотека событий, написанная на C ++ и использующая библиотеки 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 не применяет магию конвертера в этой ситуации.Когда вызывается так:

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

выдает эту ошибку:

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

Итак, мой вопрос, как я могу это исправить?Он должен был бы использовать либо перегрузку, либо оболочку, поскольку я хотел бы, чтобы библиотека оставалась вызываемой для C ++.

1 Ответ

2 голосов
/ 28 февраля 2012

Вам понадобится обертка около setResponse, которая вместо функции использует boost::python::object.Он должен хранить этот bp::object в известном месте (вероятно, переменная-член подкласса listener).

Затем передайте в базовую setResponse другую функцию c ++, которая будет знать, как искать и вызывать функцию в bp::object.Если события должны вызываться в другом потоке, вам также потребуется обеспечить надлежащую обработку глобальной блокировки интерпретатора python, как описано здесь: boost.python не поддерживает параллелизм? .

...