Обобщенный перевод исключений для Boost Python - PullRequest
8 голосов
/ 02 августа 2011

Текущий пример boost :: python для перевода конкретного исключения C ++ в python выглядит следующим образом:

void translate (const MyException& e) {
   PyErr_SetString(PyExc_RuntimeError, e.what());
}

boost::python::register_exception_translator<MyException>(translate);

К сожалению, это требует, чтобы мы написали определенную функцию для каждого из наших исключений. Мы попытались упростить это, написав переводчик обобщенных исключений:

#include <boost/python.hpp>

// Generalized exception translator for Boost Python
template <typename T> struct GeneralizedTranslator {

  public:

    void operator()(const T& cxx_except) const {
      PyErr_SetString(m_py_except, cxx_except.what());
    }

    GeneralizedTranslator(PyObject* py_except): m_py_except(py_except) {
      boost::python::register_exception_translator<T>(this);
    }

    GeneralizedTranslator(const GeneralizedTranslator& other): m_py_except(other.m_py_except) {
      //attention: do not re-register the translator!
    }

  private:

    PyObject* m_py_except;

};

//allows for a simple translation declaration, removes scope problem
template <typename T> void translate(PyObject* e) {
  ExceptionTranslator<T> my_translator(e);
}

Будет ли этот бит кода работать, вы можете обернуть исключения, которые реализуют "what ()" следующим образом:

BOOST_PYTHON_MODULE(libtest)
{
  translate<std::out_of_range>(PyExc_RuntimeError);
}

К сожалению, похоже, что boost :: python вызовет код «перевода» как функцию внутри «boost / python / detail / translate_exception.hpp» (строка 61):

translate(e);

В нашем обобщенном обработчике исключений это будет вызов GeneralizedTranslator :: operator (), который не будет работать для g ++, давая:

error: ‘translate’ cannot be used as a function

Есть ли правильный способ написать это?

1 Ответ

5 голосов
/ 02 августа 2011

Вы передаете указатель this в качестве функции перевода, и это не удается, потому что указатель на объект не может быть вызван как функция.Если вместо этого вы передадите *this, это должно сработать (обратите внимание, что это создаст копию объекта GeneralizedTranslator).Или вы можете перенести регистрацию из конструктора и позвонить

register_exception_translator<std::out_of_range>(GeneralizedTranslator<std::out_of_range>(PyExc_RuntimeError));
...