Skip to content

Instantly share code, notes, and snippets.

@pavelschon
Created August 26, 2016 19:49
Show Gist options
  • Save pavelschon/35e1e88b0f8aea38213a0cb9c8061306 to your computer and use it in GitHub Desktop.
Save pavelschon/35e1e88b0f8aea38213a0cb9c8061306 to your computer and use it in GitHub Desktop.
Translate Python exception into C++ exception (Boost::Python)
/**
* @brief Generic Python-to-C++ exception translator
* Caller provides C++ exception class, callback(), list of Python exceptions,
* which should be be handled and optional parameters to callback
*
* @param callback object, usually python function, lambda function, functor, std::bind expression or std::function
* @param exceptions list of python exceptions, e.g. { PyExc_ValueError, PyExc_TypeError }
* @param params optional parameters to callback()
* @return decltype - return value of the callback()
*
* Example:
*
* const auto exceptions = { PyExc_KeyError, PyExc_ValueError };
* const auto callback = []() { return py::dict()["key"]; }; // throws KeyError when called
*
* try
* {
* auto result = translate<std::exception>( callback, exceptions );
* }
* catch( const std::exception& )
* {
* std::cout << "key error occured" << std::endl;
* }
*
*/
template<typename EXC, typename CALLBACK, typename ITERABLE, typename... Params>
inline auto translate( const CALLBACK& callback, const ITERABLE& exceptions, Params... params ) -> decltype( callback( params... ) )
{
try
{
return callback( params... );
}
catch( const boost::python::error_already_set& )
{
PyObject *exc, *value, *traceback;
PyErr_Fetch( &exc, &value, &traceback );
for( PyObject* exc_ : exceptions )
{
if( PyErr_GivenExceptionMatches( exc, exc_ ) )
{
throw EXC();
}
}
PyErr_Restore( exc, value, traceback );
throw;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment